Problem:
アカ・ベコ捕獲作戦
怪盗アカ・ベコは大胆にも、ツルガジョーから銀のシャチホコを盗み去った。警部であるあなたは、アカ・ベコが仲間のコボウ氏にシャチホコを渡すらしいという情報を手に入れた。ただ、コボウ氏はアカ・ベコのアジトまで出向けないので、アジトの外で渡すらしい。あなたはアカ・ベコを待ち伏せして捕まえることにした。この町は古い城下町なので、道が複雑に入り組んでいて、どの道も一方通行になっている。アカ・ベコがアジトから受け渡し場所までどの経路を通るのかはわからないが、人員不足のため、待ち伏せ場所は１つに設定しなければならない。
あなたは、アジトを含むいくつかの地点を選び、それらをつなぐ道を調べ、地図を作った。地図上の地点のどこかで受け渡しが行われるらしい。受け渡し場所が判明次第、以下のように待ち伏せ場所を選ぶ。
アジトは危険なのでアジト以外の地点。
アカ・ベコがアジトから受け渡し場所までどのような経路を通っても必ず通る地点。
1, 2 の両方を満たす地点のうち、受け渡し場所にたどり着くまでに通過しなければならない地点の数がより少ない地点。ただし、コボウ氏に見つからないようにするために、1, 2 を満たす地点が他にない場合のみ、受け渡し場所を待ち伏せ場所にする。
アジトと待ち伏せ場所の候補からなる地点をつなぐ道の情報のあとに、質問として受け渡し場所が複数入力されたとき、それぞれの受け渡し場所について待ち伏せ場所を出力するプログラムを作成してください。
入力
入力は１つのデータセットからなる。入力データは以下の形式で与えられる。
N
M
s
1
t
1
:
s
M
t
M
Q
r
1
:
r
Q
１行目は２つの整数からなる。
N
(3 ≤
N
≤ 100000) は地点の数、
M
(
N
-1 ≤
M
≤ 300000) は地図に書いたすべての道の数を表す。続く
M
行に隣り合った地点の間を直接つなぐ道が与えられる。
s
i
と
t
i
(1 ≤
s
i
≠
t
i
≤
N
) は
i
番目の道のそれぞれ始点、終点となる地点の番号を表す。ただし、アジトの番号は1とし、アジトからはすべての地点へ到達できる。
続く１行に質問の数
Q
(1 ≤
Q
<
N
) が与えられる。続く
Q
行に質問が与えられる。
i
番目の質問として、受け渡し場所の番号
r
i
(2 ≤
r
i
≤
N
) が与えられる。
出力
質問ごとに、待ち伏せ場所の番号を１行に出力する。
入出力例
入力例 1
6 7
1 2
2 3
1 3
1 4
4 5
5 6
6 1
5
2
3
4
5
6
出力例 1
2
3
4
4
5
入力例 2
11 15
1 2
1 3
1 4
2 5
3 6
3 7
3 9
4 7
4 10
4 11
6 2
6 8
7 9
8 11
9 6
10
6
2
10
8
9
3
5
11
4
7
出力例 2
6
2
4
6
9
3
2
11
4
7

Submitted solutions:

code_snippet: #include <iostream>
#include <string.h>
#include <vector>
#include <queue>
using namespace std;
const int LIMIT=100003;
int ans[LIMIT];
int ans2[LIMIT];
int count[LIMIT];
vector<int> vs[LIMIT];
queue<int> qs;
int main() {
	// your code goes here
	memset(ans,0,sizeof(ans));
	memset(count,0,sizeof(count));
	memset(ans2,0,sizeof(ans2));
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int a,b;
		cin>>a>>b;
		vs[a].push_back(b);
		count[b]++;
	}
	
	qs.push(1);
	ans[1]=1;
	ans2[1]=1;
	while(qs.size()>0){
		int p1=qs.front();
		qs.pop();
		for(int i=0;i<vs[p1].size();i++){
			int p2=vs[p1][i];
			if(p2==1)continue;
			if(count[p2]==1){
				qs.push(p2);
				if(p1==1){
					ans[p2]=p2;
					ans2[p2]=p2;
				}else{
					ans[p2]=p1;
					ans2[p2]=p1;
				}
				//cout<<"p1="<<p1<<" p2="<<p2<<" ap1="<<ans[p1]<<" ap2="<<ans[p2]<<endl;
			}else if(ans[p2]==0){
				qs.push(p2);
				ans[p2]=ans[p1];
				ans2[p2]=ans2[p1];
			}else if(ans[p2]==-1){
				//なにもしない
			}else if(ans[p1]==-1){
				ans[p2]=-1;
			}else if(ans[p2]!=ans[p1]){
				ans[p2]=-1;
			}else{
				ans[p2]=ans[p1];
			}
		}
	}
	int q;
	cin>>q;
	for(int i=0;i<q;i++){
		int p1;
		cin>>p1;
		if(ans[p1]==-1||ans[p1]==1){
			cout<<p1<<endl;
		}else{
			cout<<ans[p1]<<endl;
		}
	}
	return 0;
}
accuracy: 0.5714285714285714
time_ms: 80
memory_kb: 8652
final_rank: 17

code_snippet: #include <iostream>
#include <string.h>
#include <vector>
#include <queue>
using namespace std;
const int LIMIT=100003;
int ans[LIMIT];
int ans2[LIMIT];
int count[LIMIT];
vector<int> vs[LIMIT];
queue<int> qs;
int main() {
	// your code goes here
	memset(ans,0,sizeof(ans));
	memset(count,0,sizeof(count));
	memset(ans2,0,sizeof(ans2));
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int a,b;
		cin>>a>>b;
		vs[a].push_back(b);
		count[b]++;
	}
	
	qs.push(1);
	ans[1]=1;
	ans2[1]=1;
	while(qs.size()>0){
		int p1=qs.front();
		qs.pop();
		for(int i=0;i<vs[p1].size();i++){
			int p2=vs[p1][i];
			if(p2==1)continue;
			if(count[p2]==1){
				qs.push(p2);
				if(p1==1){
					ans[p2]=p2;
					ans2[p2]=p2;
				}else{
					ans[p2]=p1;
					ans2[p2]=p1;
				}
				//cout<<"p1="<<p1<<" p2="<<p2<<" ap1="<<ans[p1]<<" ap2="<<ans[p2]<<endl;
			}else if(ans[p2]==0){
				qs.push(p2);
				ans[p2]=ans[p1];
				ans2[p2]=ans2[p1];
			}else if(ans[p2]==-1){
				//なにもしない
			}else{
				ans2[p2]=ans2[p1];
				ans[p2]=-1;
			}
		}
	}
	int q;
	cin>>q;
	for(int i=0;i<q;i++){
		int p1;
		cin>>p1;
		if(ans[p1]==-1||ans[p1]==1){
			cout<<p1<<endl;
		}else{
			cout<<ans2[p1]<<endl;
		}
	}
	return 0;
}
accuracy: 0.5714285714285714
time_ms: 80
memory_kb: 8736
final_rank: 18

code_snippet: #include <iostream>
#include <string.h>
#include <vector>
#include <queue>


using namespace std;
const int LIMIT=100003;
int ans[LIMIT];
int count[LIMIT];
vector<int> vs[LIMIT];
queue<int> qs;
int main() {
	// your code goes here
	memset(ans,0,sizeof(ans));
	memset(count,0,sizeof(count));
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int a,b;
		cin>>a>>b;
		vs[a].push_back(b);
		count[b]++;
	}
	
	qs.push(1);
	ans[1]=1;
	while(qs.size()>0){
		int p1=qs.front();
		qs.pop();
		for(int i=0;i<vs[p1].size();i++){
			int p2=vs[p1][i];
			if(p2==1)continue;
			if(count[p2]==1){
				qs.push(p2);
				if(p1==1){
					ans[p2]=p2;
				}else{
					ans[p2]=p1;
				}
				//cout<<"p1="<<p1<<" p2="<<p2<<" ap1="<<ans[p1]<<" ap2="<<ans[p2]<<endl;
			}else if(ans[p2]==0){
				qs.push(p2);
				ans[p2]=ans[p1];
			}else if(ans[p2]==-1){
				//なにもしない
			}else if(ans[p1]==ans[p2]){
				//何もしない
			}else if(ans[p1]!=ans[p2]){
				ans[p2]=-1;
			}
		}
	}
	int q;
	cin>>q;
	for(int i=0;i<q;i++){
		int p1;
		cin>>p1;
		if(ans[p1]==-1||ans[p1]==1){
			cout<<p1<<endl;
		}else{
			cout<<ans[p1]<<endl;
		}
	}
	return 0;
}
accuracy: 0.5714285714285714
time_ms: 80
memory_kb: 8256
final_rank: 16

code_snippet: #include <iostream>
#include <string.h>
#include <vector>
#include <queue>


using namespace std;
const int LIMIT=100003;
int ans[LIMIT];
int count[LIMIT];
vector<int> vs[LIMIT];
queue<int> qs;
int main() {
	// your code goes here
	memset(ans,0,sizeof(ans));
	memset(count,0,sizeof(count));
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int a,b;
		cin>>a>>b;
		vs[a].push_back(b);
		count[b]++;
	}
	
	qs.push(1);
	ans[1]=1;
	while(qs.size()>0){
		int p1=qs.front();
		qs.pop();
		for(int i=0;i<vs[p1].size();i++){
			int p2=vs[p1][i];
			if(p2==1)continue;
			if(count[p2]==1){
				qs.push(p2);
				if(p1==1){
					ans[p2]=p2;
				}else{
					ans[p2]=p1;
				}
				//cout<<"p1="<<p1<<" p2="<<p2<<" ap1="<<ans[p1]<<" ap2="<<ans[p2]<<endl;
			}else if(ans[p2]==0){
				qs.push(p2);
				ans[p2]=ans[p1];
			}else if(ans[p2]==-1){
				//なにもしない
			}else if(ans[p1]==ans[p2]){
				//何もしない
			}else if(ans[p1]!=ans[p2]){
				ans[p2]=-1;
			}
		}
	}
	int q;
	cin>>q;
	for(int i=0;i<q;i++){
		int p1;
		cin>>p1;
		if(ans[p1]==-1){
			cout<<p1<<endl;
		}else{
			cout<<ans[p1]<<endl;
		}
	}
	return 0;
}
accuracy: 0.42857142857142855
time_ms: 80
memory_kb: 8184
final_rank: 20

code_snippet: #include<iostream>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
#include<functional>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cassert>
#include<ctime>
using namespace std;

#define mind(a,b) (a>b?b:a)
#define maxd(a,b) (a>b?a:b)
#define absd(x) (x<0?-(x):x)
#define pow2(x) ((x)*(x))
#define rep(i,n) for(int i=0; i<n; ++i)
#define repr(i,n) for(int i=n-1; i>=0; --i)
#define repl(i,s,n) for(int i=s; i<=n; ++i)
#define replr(i,s,n) for(int i=n; i>=s; --i)
#define repf(i,s,n,j) for(int i=s; i<=n; i+=j)
#define repe(e,obj) for(auto e : obj)

#define SP << " " <<
#define COL << " : " <<
#define COM << ", " <<
#define ARR << " -> " <<
#define PNT(STR) cout << STR << endl
#define POS(X,Y) "(" << X << ", " << Y << ")"
#define DEB(A) " (" << #A << ") " << A
#define DEBREP(i,n,val) for(int i=0; i<n; ++i) cout << val << " "; cout << endl
#define ALL(V) (V).begin(), (V).end()
#define INF 1000000007
#define INFLL 1000000000000000007LL
#define EPS 1e-9

typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
#define P_TYPE int
typedef pair<P_TYPE, P_TYPE> P;
typedef pair<P, P_TYPE> PI;
typedef pair<P_TYPE, P> IP;
typedef pair<P, P> PP;
typedef priority_queue<P, vector<P>, greater<P> > pvqueue;

#define N 100003

int n;
vector<int> g[N];

vector<int> vs;
int order[N];
int prt[N];
int doms[N], semi[N];
int anc[N], label[N];
vector<int> rg[N];

inline void link(int v, int w) {
  anc[w] = v;
}

int compress(int v, int w) {
  if(w == anc[w]) {
    return w;
  }

  anc[v] = compress(w, anc[w]);
  if(label[w] < label[v]) {
    label[v] = label[w];
  }
  return anc[v];
}

inline int eval(int v) {
  if(v == anc[v]) {
    return label[v];
  }

  compress(v, anc[v]);
  return label[v];
}

void dfs(int v) {
  order[v] = vs.size();
  vs.push_back(v);
  for(int w : g[v]) {
    if(order[w] != -1) continue;
    prt[w] = v;
    dfs(w);
  }
}

void dominator(int s) {
  for(int i=0; i<n; ++i) order[i] = -1, prt[i] = -1;
  vs.reserve(n);

  dfs(s);

  for(int i=0; i<n; ++i) semi[i] = label[i] = order[i], doms[i] = -1;
  for(int i=0; i<n; ++i) anc[i] = i;

  for(int v=0; v<n; ++v) {
    for(int w : g[v]) {
      rg[w].push_back(v);
    }
  }

  for(int i=n-1; i>0; --i) {
    int w = vs[i];
    for(int v : rg[w]) {
      int s_min = eval(v);
      if(s_min < semi[w]) semi[w] = s_min;
    }
    label[w] = semi[w];
    link(prt[w], w);
  }

  doms[s] = s;
  for(int i=1; i<n; ++i) {
    int w = vs[i];
    int x = prt[w];
    while(semi[w] < order[x]) x = doms[x];
    doms[w] = x;
  }
}

int main() {
  int m; cin >> n >> m;
  rep(i, m) {
    int s, t; cin >> s >> t; --s; --t;
    g[s].push_back(t);
  }
  dominator(0);
  int q; cin >> q;
  rep(i, q) {
    int r; cin >> r; --r;
    cout << (doms[r] != 0 ? doms[r]+1 : r+1) << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 19320
final_rank: 4

code_snippet: #include<iostream>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
#include<functional>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cassert>
#include<ctime>
using namespace std;

#define mind(a,b) (a>b?b:a)
#define maxd(a,b) (a>b?a:b)
#define absd(x) (x<0?-(x):x)
#define pow2(x) ((x)*(x))
#define rep(i,n) for(int i=0; i<n; ++i)
#define repr(i,n) for(int i=n-1; i>=0; --i)
#define repl(i,s,n) for(int i=s; i<=n; ++i)
#define replr(i,s,n) for(int i=n; i>=s; --i)
#define repf(i,s,n,j) for(int i=s; i<=n; i+=j)
#define repe(e,obj) for(auto e : obj)

#define SP << " " <<
#define COL << " : " <<
#define COM << ", " <<
#define ARR << " -> " <<
#define PNT(STR) cout << STR << endl
#define POS(X,Y) "(" << X << ", " << Y << ")"
#define DEB(A) " (" << #A << ") " << A
#define DEBREP(i,n,val) for(int i=0; i<n; ++i) cout << val << " "; cout << endl
#define ALL(V) (V).begin(), (V).end()
#define INF 1000000007
#define INFLL 1000000000000000007LL
#define EPS 1e-9

typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
#define P_TYPE int
typedef pair<P_TYPE, P_TYPE> P;
typedef pair<P, P_TYPE> PI;
typedef pair<P_TYPE, P> IP;
typedef pair<P, P> PP;
typedef priority_queue<P, vector<P>, greater<P> > pvqueue;

#define N 100003

int n;
vector<int> g[N];

vector<int> vs;
int order[N];
int prt[N];
int doms[N], semi[N];
int anc[N], label[N];
vector<int> rg[N], bucket[N];

inline void link(int v, int w) {
  anc[w] = v;
}

int compress(int v, int w) {
  if(w == anc[w]) {
    return w;
  }

  anc[v] = compress(w, anc[w]);
  if(semi[label[w]] < semi[label[v]]) {
    label[v] = label[w];
  }
  return anc[v];
}

inline int eval(int v) {
  if(v == anc[v]) {
    return v;
  }

  compress(v, anc[v]);
  return label[v];
}

void dfs(int v) {
  order[v] = vs.size();
  vs.push_back(v);
  for(int w : g[v]) {
    if(order[w] != -1) continue;
    prt[w] = v;
    dfs(w);
  }
}

void dominator(int s) {
  for(int i=0; i<n; ++i) order[i] = -1, prt[i] = -1;
  vs.reserve(n);

  dfs(s);

  for(int i=0; i<n; ++i) semi[i] = order[i], doms[i] = -1;
  for(int i=0; i<n; ++i) anc[i] = label[i] = i;

  for(int v=0; v<n; ++v) {
    for(int w : g[v]) {
      rg[w].push_back(v);
    }
  }

  for(int i=n-1; i>0; --i) {
    int w = vs[i];
    for(int v : bucket[w]) {
      int u = eval(v);
      doms[v] = (semi[u] < semi[v] ? u : w);
    }
    for(int v : rg[w]) {
      int u = eval(v);
      if(semi[u] < semi[w]) {
        semi[w] = semi[u];
      }
    }
    if(vs[semi[w]] != prt[w]) {
      bucket[vs[semi[w]]].push_back(w);
    } else {
      doms[w] = prt[w];
    }
    link(prt[w], w);
  }
  for(int v : bucket[s]) doms[v] = s;

  for(int i=1; i<n; ++i) {
    int w = vs[i];
    if(doms[w] != vs[semi[w]]) {
      doms[w] = doms[doms[w]];
    }
  }
  doms[s] = s;
}

int main() {
  int m; cin >> n >> m;
  rep(i, m) {
    int s, t; cin >> s >> t; --s; --t;
    g[s].push_back(t);
  }
  dominator(0);
  int q; cin >> q;
  rep(i, q) {
    int r; cin >> r; --r;
    cout << (doms[r] != 0 ? doms[r]+1 : r+1) << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 22084
final_rank: 5

code_snippet: #include<iostream>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
#include<functional>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cassert>
#include<ctime>
using namespace std;

#define mind(a,b) (a>b?b:a)
#define maxd(a,b) (a>b?a:b)
#define absd(x) (x<0?-(x):x)
#define pow2(x) ((x)*(x))
#define rep(i,n) for(int i=0; i<n; ++i)
#define repr(i,n) for(int i=n-1; i>=0; --i)
#define repl(i,s,n) for(int i=s; i<=n; ++i)
#define replr(i,s,n) for(int i=n; i>=s; --i)
#define repf(i,s,n,j) for(int i=s; i<=n; i+=j)
#define repe(e,obj) for(auto e : obj)

#define SP << " " <<
#define COL << " : " <<
#define COM << ", " <<
#define ARR << " -> " <<
#define PNT(STR) cout << STR << endl
#define POS(X,Y) "(" << X << ", " << Y << ")"
#define DEB(A) " (" << #A << ") " << A
#define DEBREP(i,n,val) for(int i=0; i<n; ++i) cout << val << " "; cout << endl
#define ALL(V) (V).begin(), (V).end()
#define INF 1000000007
#define INFLL 1000000000000000007LL
#define EPS 1e-9

typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
#define P_TYPE int
typedef pair<P_TYPE, P_TYPE> P;
typedef pair<P, P_TYPE> PI;
typedef pair<P_TYPE, P> IP;
typedef pair<P, P> PP;
typedef priority_queue<P, vector<P>, greater<P> > pvqueue;

#define N 100003

int n;
vector<int> g[N];

vector<int> vs;
int order[N];
int prt[N];
int doms[N], semi[N];
int anc[N], label[N];
vector<int> rg[N], bucket[N];

inline void link(int v, int w) {
  anc[w] = v;
}

int compress(int v, int w) {
  if(w == anc[w]) {
    return w;
  }

  anc[v] = compress(w, anc[w]);
  if(semi[label[w]] < semi[label[v]]) {
    label[v] = label[w];
  }
  return anc[v];
}

inline int eval(int v) {
  if(v == anc[v]) {
    return v;
  }

  compress(v, anc[v]);
  return label[v];
}

void dfs(int v) {
  order[v] = vs.size();
  vs.push_back(v);
  for(int w : g[v]) {
    if(order[w] != -1) continue;
    prt[w] = v;
    dfs(w);
  }
}

void prepare(int s) {
  for(int i=0; i<n; ++i) order[i] = -1, prt[i] = -1;
  vs.reserve(n);

  dfs(s);
}

void dominator(int s) {
  prepare(s);
  for(int i=0; i<n; ++i) semi[i] = order[i], doms[i] = -1;
  for(int i=0; i<n; ++i) anc[i] = label[i] = i;

  for(int v=0; v<n; ++v) {
    for(int w : g[v]) {
      rg[w].push_back(v);
    }
  }

  for(int i=n-1; i>0; --i) {
    int w = vs[i];
    for(int v : bucket[w]) {
      int u = eval(v);
      doms[v] = (semi[u] < semi[v] ? u : w);
    }
    for(int v : rg[w]) {
      int u = eval(v);
      if(semi[u] < semi[w]) {
        semi[w] = semi[u];
      }
    }
    if(vs[semi[w]] != prt[w]) {
      bucket[vs[semi[w]]].push_back(w);
    } else {
      doms[w] = prt[w];
    }
    link(prt[w], w);
  }
  for(int v : bucket[s]) doms[v] = s;

  for(int i=1; i<n; ++i) {
    int w = vs[i];
    if(doms[w] != vs[semi[w]]) {
      doms[w] = doms[doms[w]];
    }
  }
  doms[s] = s;
}

int main() {
  int m; cin >> n >> m;
  rep(i, m) {
    int s, t; cin >> s >> t; --s; --t;
    g[s].push_back(t);
  }
  dominator(0);
  int q; cin >> q;
  rep(i, q) {
    int r; cin >> r; --r;
    cout << (doms[r] != 0 ? doms[r]+1 : r+1) << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 22188
final_rank: 6

code_snippet: #include <iostream>
#include <vector>
#include<iomanip>
#include<functional>
#include<algorithm>
#include<deque>
#include<math.h>
#include<set>
#include<cstdio>
#include<string>
#include<queue>
#include<complex>
#include<numeric>
#include<stack>
#include<unordered_map>
#include<map>
#include <cassert>
using namespace std;
#define rep(i,n) for(int i = 0;i<n;i++)
#define req(i,n) for(ll i = 1;i<=n;i++)
#define rrep(i,n) for(int i = n-1;i>=0;i--)
#define ALL(a) a.begin(),a.end()
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
typedef long long ll;
typedef long double ld;
const ll mod = 1e9 + 7;
struct DominatorTree {// 根 s からある頂点 tへ通る時の必ず通る点のうち最もtに近い点
    struct UnionFind {
        vector<int>& semi;
        vector<int>ps, ms;
        UnionFind(vector<int>& semi) :semi(semi), ps(semi.size()), ms(semi.size()) {
            iota(ALL(ps), 0); iota(ALL(ms), 0);
        }int find(int v) {
            if (ps[v] == v)return v;
            int r = find(ps[v]);
            if (semi[ms[v]] > semi[ms[ps[v]]]) ms[v] = ms[ps[v]];
            return ps[v] = r;
        }int eval(int v) {
            find(v); return ms[v];
        }void link(int p, int v) { ps[v] = p; }
    }; vector<vector<int>> G, R;
    vector<int> ord, par, idom, semi;
    DominatorTree(int n): G(n), R(n), par(n), idom(n, -1), semi(n, -1) {
        ord.reserve(n);
    }void add_edge(int u, int v) {
        G[u].push_back(v); R[v].push_back(u);
    }void dfs(int v) {
        semi[v] = ord.size(); ord.push_back(v);
        for (int u : G[v]) {
            if (~semi[u])continue;
            par[u] = v; dfs(u);
        }
    }void build(int rt) {
        dfs(rt); int n = G.size();
        vector<vector<int>> bkt(n);
        UnionFind uf(semi); vector<int> us(n);
        rrep(i, ord.size()) {
            int v = ord[i];
            for (int u : R[v]) {
                if (semi[u] < 0)continue;
                u = uf.eval(u);
                if (semi[v] > semi[u])semi[v] = semi[u];
            }bkt[ord[semi[v]]].push_back(v);
            for (int u : bkt[par[v]]) us[u] = uf.eval(u);
            bkt[par[v]].clear(); uf.link(par[v], v);
        }req(i, ord.size()-1) {
            int v = ord[i], u = us[v];
            idom[v] = (semi[v] == semi[u] ? semi[v] : idom[u]);
        }req(i, ord.size() - 1) {
            int v = ord[i]; idom[v] = ord[idom[v]];
        }idom[rt] = rt;
    }int operator[](int k) { return idom[k]; }
};
int main() {
    int n, m, q,a,b; cin >> n >> m;
    DominatorTree G(n);
    rep(i, m) {
        cin >> a >> b; a--; b--;
        G.add_edge(a, b);
    }cin >> q; G.build(0);
    rep(i, q) {
        cin >> a; a--;
        if (G[a] == 0) cout << a + 1 << endl;
        else cout << G[a] + 1 << endl;
    }
}
accuracy: 1
time_ms: 260
memory_kb: 22208
final_rank: 8

code_snippet: #include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define modulo 1000000007
#define mod(mod_x) ((((long long)mod_x+modulo))%modulo)
#define Inf 1000000000000000000

struct dominator_tree{
	
	
	struct potentialized_dsu {
		using S = pair<int,int>;
	  public:
		potentialized_dsu() : _n(0) {}
		potentialized_dsu(int n) : _n(n), parent_or_size(n, -1), d(n,e()) {}

		int merge(int a, int b, S v) {
			assert(0 <= a && a < _n);
			assert(0 <= b && b < _n);
			int x = leader(a), y = leader(b);
			if (x == y) return x;
			
			d[y] = op(d[y],op(d[x],v));
			
			parent_or_size[x] += parent_or_size[y];
			parent_or_size[y] = x;
			
			return x;
		}

		bool same(int a, int b) {
			assert(0 <= a && a < _n);
			assert(0 <= b && b < _n);
			return leader(a) == leader(b);
		}

		int leader(int a) {
			assert(0 <= a && a < _n);
			if (parent_or_size[a] < 0) return a;
			int l = leader(parent_or_size[a]);
			if(parent_or_size[a] != l){
				d[a] = op(d[parent_or_size[a]],d[a]);
				parent_or_size[a] = l;
			}
			return parent_or_size[a];
		}

		int size(int a) {
			assert(0 <= a && a < _n);
			return -parent_or_size[leader(a)];
		}
		
		S get(int a){
			assert(0 <= a && a < _n);
			leader(a);
			return d[a];
		}

		std::vector<std::vector<int>> groups() {
			std::vector<int> leader_buf(_n), group_size(_n);
			for (int i = 0; i < _n; i++) {
				leader_buf[i] = leader(i);
				group_size[leader_buf[i]]++;
			}
			std::vector<std::vector<int>> result(_n);
			for (int i = 0; i < _n; i++) {
				result[i].reserve(group_size[i]);
			}
			for (int i = 0; i < _n; i++) {
				result[leader_buf[i]].push_back(i);
			}
			result.erase(
				std::remove_if(result.begin(), result.end(),
							   [&](const std::vector<int>& v) { return v.empty(); }),
				result.end());
			return result;
		}
		
		pair<int,int> op(pair<int,int> a,pair<int,int> b){
			return min(a,b);
		}

		pair<int,int> e(){
			return make_pair(1000000000,0);
		}

	  private:
		int _n;
		// root node: -1 * component size
		// otherwise: parent
		std::vector<int> parent_or_size;
		std::vector<S> d;
	};

	dominator_tree(){
	}
	
	
	vector<vector<int>> get(vector<vector<int>> E,int r){

		int n = E.size();
		vector<int> ind;
		vector<int> pos(n,n);
		vector<int> p(n,-1);
		dfs(r,E,ind,pos,p);

		vector<vector<int>> rE(n);
		rep(i,E.size()){
			rep(j,E[i].size()){
				rE[E[i][j]].push_back(i);
			}
		}
		

		vector<pair<int,int>> sdom(n,make_pair(n,n));
		vector<pair<int,int>> idom(n,make_pair(n,n));
		vector<vector<int>> L(n);
		potentialized_dsu D(n);
		
		for(int i=ind.size()-1;i>=1;i--){
			int u = ind[i];
			rep(j,rE[u].size()){
				int v = rE[u][j];
				sdom[u] = min(sdom[u],make_pair(pos[v],u));
				sdom[u] = min(sdom[u],D.get(v));
			}
			sdom[u].second = u;
			
			L[ind[sdom[u].first]].push_back(u);
			
			rep(j,L[p[u]].size()){
				int v = L[p[u]][j];
				idom[v] = min(D.get(v),sdom[u]);
			}
			L[p[u]].clear();
			D.merge(p[u],u,sdom[u]);
			
		}
		
		rep(i,ind.size()){
			if(i==0)continue;
			int u = ind[i];
			if(idom[u].first==n){
				//idom[u] = make_pair(sdom[u].first,u);
			}
			else if(sdom[u].first == sdom[idom[u].second].first){
				idom[u] = sdom[u];
			}
			else{
				idom[u] = idom[idom[u].second];
			}
		}

		vector<vector<int>> ret(n);
		rep(i,n){
			if(idom[i].first==n)continue;
			ret[ind[idom[i].first]].push_back(i);
		}
		return ret;
		
	}
	
	void dfs(int cur,vector<vector<int>> &E,vector<int> &ind,vector<int> &pos,vector<int> &p){
		pos[cur] = ind.size();
		ind.push_back(cur);
		rep(i,E[cur].size()){
			int to = E[cur][i];
			if(pos[to]!=E.size())continue;
			p[to] = cur;
			dfs(to,E,ind,pos,p);
		}
	}
	
	
	
};

int main(){
	
	int n,m;
	cin>>n>>m;
	
	vector<vector<int>> E(n);
	rep(i,m){
		int u,v;
		scanf("%d %d",&u,&v);
		u--;v--;
		E[u].push_back(v);
	}
	
	dominator_tree D;
	auto ret = D.get(E,0);
	
	vector<int> ans(n);
	
	rep(i,n){
		rep(j,ret[i].size()){
			int x = i+1;
			if(i==0)x = ret[i][j]+1;
			ans[ret[i][j]] = x;
		}
	}
	
	int Q;
	cin>>Q;
	
	rep(_,Q){
		int r;
		scanf("%d",&r);
		printf("%d\n",ans[r-1]);
	}
		
		
	
    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 35756
final_rank: 7

code_snippet: #line 1 "0294.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/0294"

#include <bits/stdc++.h>  // clang-format off
using Int = long long;
#define REP_(i, a_, b_, a, b, ...) for (Int i = (a), lim##i = (b); i < lim##i; i++)
#define REP(i, ...) REP_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)
#define ALL(v) std::begin(v), std::end(v)
struct SetupIO { SetupIO() { std::cin.tie(nullptr), std::ios::sync_with_stdio(false), std::cout << std::fixed << std::setprecision(13); } } setup_io;
#ifndef dump
#define dump(...)
#endif  // clang-format on

/**
 *    author:  knshnb
 *    created: Sat Aug  1 16:21:06 JST 2020
 **/

#define CALL_FROM_TEST
#line 1 "/Users/knshnb/competitive_programming/competitive_library/src/Graph/DominatorTree.hpp"
/// @docs src/Graph/DominatorTree.md
// 根付き森と、根から各頂点までのaggregationを管理
template <class T, class F> struct DirectedUnionFind {
    std::vector<int> par;
    std::vector<T> val;
    F op;
    DirectedUnionFind(F op_) : op(op_) {}
    void set_by_vector(const std::vector<T>& val_) {
        par.resize(val_.size()), std::iota(par.begin(), par.end(), 0);
        val = val_;
    }
    void set_by_value(int n, T a) {
        par.resize(n), std::iota(par.begin(), par.end(), 0);
        val.resize(n, a);
    }
    int compress(int v) {
        if (par[v] == v) return v;
        int root = compress(par[v]);
        val[v] = op(val[par[v]], val[v]);
        return par[v] = root;
    }
    int eval(int v) {
        compress(v);
        return val[v];
    }
    // rootをtoにつなげる
    void link(int to, int root) {
        assert(par[root] == root);
        par[root] = to;
    }
};
template <class T, class F> DirectedUnionFind<T, F> make_directed_unionfind(F op_) {
    return DirectedUnionFind<T, F>(op_);
}

// 親をさすvectorを返す。rootの親はroot、rootから到達できない頂点の親は-1
std::vector<int> construct_domnator_tree(const std::vector<std::vector<int>>& edge, int root) {
    int n = edge.size();
    std::vector<std::vector<int>> redge(n);
    for (int u = 0; u < n; u++)
        for (int v : edge[u]) redge[v].push_back(u);
    // dfs木を作る
    std::vector<int> par(n, -1), to_vertex, to_ord(n, -1);
    auto dfs = [&](auto&& self, int v) -> void {
        to_ord[v] = to_vertex.size();
        to_vertex.push_back(v);
        for (int u : edge[v]) {
            if (to_ord[u] != -1) continue;
            self(self, u);
            par[to_ord[u]] = to_ord[v];
        }
    };
    dfs(dfs, root);
    int m = to_vertex.size();  // rootから到達可能な頂点数
    // dfs逆順
    std::vector<int> sdom(m), U(m, -1);
    for (int i = 1; i < m; i++) sdom[i] = i;  // Theorem 4の左側をカバーできるように、iで初期化しておく
    auto uf = make_directed_unionfind<int>([&](int i, int j) { return sdom[i] < sdom[j] ? i : j; });
    uf.set_by_value(m, 0);
    for (int i = 0; i < m; i++) uf.val[i] = i;
    std::vector<std::vector<int>> bucket(n);
    for (int i = m - 1; i >= 1; i--) {
        // dfs逆順にsemidominatorを求める(Theorem 4)
        for (int v : redge[to_vertex[i]]) {
            int j = to_ord[v];
            if (j == -1) continue;  // rootから到達できない頂点
            sdom[i] = std::min(sdom[i], sdom[uf.eval(j)]);
        }
        // Corollary 1
        bucket[sdom[i]].push_back(i);
        for (int j : bucket[par[i]]) U[j] = uf.eval(j);
        uf.link(par[i], i);
    }
    // dfs順にimmediate dominatorを求める
    std::vector<int> idom(m, -1);
    for (int i = 1; i < m; i++) {
        int u = U[i];
        idom[i] = sdom[i] == sdom[u] ? sdom[i] : idom[u];
    }
    // dfs順序からもとの頂点番号で表示したものに直す
    std::vector<int> ret(n, -1);
    for (int i = 1; i < m; i++) {
        ret[to_vertex[i]] = to_vertex[idom[i]];
    }
    ret[root] = root;
    return ret;
}
#line 20 "0294.test.cpp"
#undef CALL_FROM_TEST

signed main() {
    Int n, m;
    std::cin >> n >> m;
    std::vector<std::vector<int>> g(n);
    for (int i = 0; i < m; i++) {
        Int u, v;
        std::cin >> u >> v, u--, v--;
        g[u].push_back(v);
    }
    std::vector<int> dtree = construct_domnator_tree(g, 0);
    Int Q;
    std::cin >> Q;
    REP(q, Q) {
        Int r;
        std::cin >> r, r--;
        std::cout << (dtree[r] == 0 ? r : dtree[r]) + 1 << "\n";
    }
}
accuracy: 1
time_ms: 90
memory_kb: 23660
final_rank: 2

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

class DominatorTree {
    int n;
    void unite(int x, int y){
        uf_par[y] = x;
    }

    int compress(int x){
        if(uf_par[x] == x) return x;
        int r = compress(uf_par[x]);
        if(semi[m[x]] > semi[m[uf_par[x]]]) m[x] = m[uf_par[x]];
        return uf_par[x] = r;
    }

    int eval(int x){
        compress(x);
        return m[x];
    }


    void dfs(int x, int &cur){
        semi[x] = cur;
        ord[cur++] = x;
        for (auto &&i : G[x]) {
            if(!~semi[i]){
                par[i] = x;
                dfs(i, cur);
            }
        }
    }
public:
    DominatorTree(int n) : n(n), G(n), Grev(n), idom(n), semi(n), ord(n), par(n), uf_par(n), m(n), tmp(n), U(n) {}

    vector<vector<int>> G, Grev, tmp;
    vector<int> semi, ord, par, uf_par, m, U, idom;

    void add_edge(int a, int b){
        G[a].emplace_back(b);
        Grev[b].emplace_back(a);
    }
    void build(int root){
        for (int i = 0; i < n; ++i) uf_par[i] = i, m[i] = i, semi[i] = -1, idom[i] = -1;
        int cur = 0;
        dfs(root, cur);
        for (int i = n-1; i >= 0; --i) {
            int a = ord[i];
            for (auto &&b : Grev[a]) {
                if(~semi[b]){
                    int c = eval(b);
                    semi[a] = min(semi[a], semi[c]);
                }
            }
            tmp[ord[semi[a]]].emplace_back(a);
            for (auto &&b : tmp[par[a]]) U[b] = eval(b);
            tmp[par[a]].clear();
            unite(par[a], a);
        }
        for (int i = 1; i < n; ++i) {
            int a = ord[i], b = U[a];
            if(semi[a] == semi[b]) idom[a] = semi[a];
            else idom[a] = idom[b];
        }
        for (int i = 1; i < n; ++i) {
            int a = ord[i];
            idom[a] = ord[idom[a]];
        }
        idom[root] = -1;
    }

};

int main() {
    int n, m;
    cin >> n >> m;
    DominatorTree G(n);
    for (int i = 0; i < m; ++i) {
        int s, t;
        cin >> s >> t;
        s--; t--;
        G.add_edge(s, t);
    }
    G.build(0);
    int q;
    cin >> q;
    for (int i = 0; i < q; ++i) {
        int x;
        cin >> x;
        x--;
        if(!G.idom[x]) printf("%d\n", x+1);
        else printf("%d\n", G.idom[x]+1);
    }
    return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 22316
final_rank: 9

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

class DominatorTree {
    int n;
    void unite(int x, int y){
        uf_par[y] = x;
    }

    int compress(int x){
        if(uf_par[x] == x) return x;
        int r = compress(uf_par[x]);
        if(semi[m[x]] > semi[m[uf_par[x]]]) m[x] = m[uf_par[x]];
        return uf_par[x] = r;
    }

    int eval(int x){
        compress(x);
        return m[x];
    }


    void dfs(int x, int &cur){
        semi[x] = cur;
        ord[cur++] = x;
        for (auto &&i : G[x]) {
            if(!~semi[i]){
                par[i] = x;
                dfs(i, cur);
            }
        }
    }
public:
    DominatorTree(int n) : n(n), G(n), Grev(n), idom(n), semi(n), ord(n), par(n), uf_par(n), m(n), tmp(n), U(n) {}

    vector<vector<int>> G, Grev, tmp;
    vector<int> semi, ord, par, uf_par, m, U, idom;

    void add_edge(int a, int b){
        G[a].emplace_back(b);
        Grev[b].emplace_back(a);
    }
    void build(int root){
        for (int i = 0; i < n; ++i) uf_par[i] = i, m[i] = i, semi[i] = -1, idom[i] = -1;
        int cur = 0;
        dfs(root, cur);
        for (int i = n-1; i >= 0; --i) {
            int a = ord[i];
            for (auto &&b : Grev[a]) {
                if(~semi[b]){
                    int c = eval(b);
                    semi[a] = min(semi[a], semi[c]);
                }
            }
            tmp[ord[semi[a]]].emplace_back(a);
            for (auto &&b : tmp[par[a]]) U[b] = eval(b);
            tmp[par[a]].clear();
            unite(par[a], a);
        }
        for (int i = 1; i < n; ++i) {
            int a = ord[i], b = U[a];
            if(semi[a] == semi[b]) idom[a] = semi[a];
            else idom[a] = semi[b];
        }
        for (int i = 1; i < n; ++i) {
            int a = ord[i];
            idom[a] = ord[idom[a]];
        }
        idom[root] = -1;
    }

};

int main() {
    int n, m;
    cin >> n >> m;
    DominatorTree G(n);
    for (int i = 0; i < m; ++i) {
        int s, t;
        cin >> s >> t;
        s--; t--;
        G.add_edge(s, t);
    }
    G.build(0);
    int q;
    cin >> q;
    for (int i = 0; i < q; ++i) {
        int x;
        cin >> x;
        x--;
        if(!G.idom[x]) printf("%d\n", x+1);
        else printf("%d\n", G.idom[x]+1);
    }
    cout.flush();
    return 0;
}
accuracy: 0.8571428571428571
time_ms: 250
memory_kb: 22280
final_rank: 12

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

class DominatorTree {
    int n;
    void unite(int x, int y){
        uf_par[y] = x;
    }

    int compress(int x){
        if(uf_par[x] == x) return x;
        int r = compress(uf_par[x]);
        if(semi[m[x]] > semi[m[uf_par[x]]]) m[x] = m[uf_par[x]];
        return uf_par[x] = r;
    }

    int eval(int x){
        compress(x);
        return m[x];
    }


    void dfs(int x, int &cur){
        semi[x] = cur;
        ord[cur++] = x;
        for (auto &&i : G[x]) {
            if(!~semi[i]){
                par[i] = x;
                dfs(i, cur);
            }
        }
    }
public:
    DominatorTree(int n) : n(n), G(n), Grev(n), idom(n), semi(n), ord(n), par(n), uf_par(n), m(n), tmp(n), U(n) {}

    vector<vector<int>> G, Grev, tmp;
    vector<int> semi, ord, par, uf_par, m, U, idom;

    void add_edge(int a, int b){
        G[a].emplace_back(b);
        Grev[b].emplace_back(a);
    }
    void build(int root){
        for (int i = 0; i < n; ++i) uf_par[i] = i, m[i] = i, semi[i] = -1, idom[i] = -1;
        int cur = 0;
        dfs(root, cur);
        for (int i = n-1; i >= 0; --i) {
            int a = ord[i];
            for (auto &&b : Grev[a]) {
                if(~semi[b]){
                    int c = eval(b);
                    semi[a] = min(semi[a], semi[c]);
                }
            }
            tmp[ord[semi[a]]].emplace_back(a);
            for (auto &&b : tmp[par[a]]) U[b] = eval(b);
            tmp[par[a]].clear();
            unite(par[a], a);
        }
        for (int i = 1; i < n; ++i) {
            int a = ord[i], b = U[a];
            if(semi[a] == semi[b]) idom[a] = semi[a];
            else idom[a] = semi[b];
        }
        for (int i = 1; i < n; ++i) {
            int a = ord[i];
            idom[a] = ord[idom[a]];
        }
        idom[root] = -1;
    }

};

int main() {
    int n, m;
    cin >> n >> m;
    DominatorTree G(n);
    for (int i = 0; i < m; ++i) {
        int s, t;
        cin >> s >> t;
        s--; t--;
        G.add_edge(s, t);
    }
    G.build(0);
    int q;
    cin >> q;
    for (int i = 0; i < q; ++i) {
        int x;
        cin >> x;
        x--;
        if(!G.idom[x]) printf("%d\n", x+1);
        else printf("%d\n", G.idom[x]+1);
    }
    return 0;
}
accuracy: 0.8571428571428571
time_ms: 250
memory_kb: 22356
final_rank: 13

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

class DominatorTree {
    int n;
    void unite(int x, int y){
        uf_par[y] = x;
    }

    int compress(int x){
        if(uf_par[x] == x) return x;
        int r = compress(uf_par[x]);
        if(semi[m[x]] > semi[m[uf_par[x]]]) m[x] = m[uf_par[x]];
        return uf_par[x] = r;
    }

    int eval(int x){
        compress(x);
        return m[x];
    }


    void dfs(int x, int &cur){
        semi[x] = cur;
        ord[cur++] = x;
        for (auto &&i : G[x]) {
            if(!~semi[i]){
                par[i] = x;
                dfs(i, cur);
            }
        }
    }
public:
    DominatorTree(int n) : n(n), G(n), Grev(n), idom(n), semi(n), ord(n), par(n), uf_par(n), m(n), tmp(n), U(n) {}

    vector<vector<int>> G, Grev, tmp;
    vector<int> semi, ord, par, uf_par, m, U, idom;

    void add_edge(int a, int b){
        G[a].emplace_back(b);
        Grev[b].emplace_back(a);
    }
    void build(int root){
        for (int i = 0; i < n; ++i) uf_par[i] = i, m[i] = i, semi[i] = -1;
        int cur = 0;
        dfs(root, cur);
        for (int i = n-1; i >= 0; --i) {
            int a = ord[i];
            for (auto &&b : Grev[a]) {
                if(~semi[b]){
                    int c = eval(b);
                    semi[a] = min(semi[a], semi[c]);
                }
            }
            tmp[ord[semi[a]]].emplace_back(a);
            for (auto &&b : tmp[par[a]]) U[b] = eval(b);
            tmp[par[a]].clear();
            unite(par[a], a);
        }
        for (int i = 1; i < n; ++i) {
            int a = ord[i], b = U[a];
            if(semi[a] == semi[b]) idom[a] = semi[a];
            else idom[a] = semi[b];
        }
        for (int i = 1; i < n; ++i) {
            int a = ord[i];
            idom[a] = ord[idom[a]];
        }
        idom[root] = -1;
    }

};

int main() {
    int n, m;
    cin >> n >> m;
    DominatorTree G(n);
    for (int i = 0; i < m; ++i) {
        int s, t;
        cin >> s >> t;
        s--; t--;
        G.add_edge(s, t);
    }
    G.build(0);
    int q;
    cin >> q;
    for (int i = 0; i < q; ++i) {
        int x;
        cin >> x;
        x--;
        if(!G.idom[x]) printf("%d\n", x+1);
        else printf("%d\n", G.idom[x]+1);
    }
    return 0;
}
accuracy: 0.8571428571428571
time_ms: 260
memory_kb: 22440
final_rank: 14

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

class DominatorTree {
    int n;
    void unite(int x, int y){
        uf_par[y] = x;
    }

    int compress(int x){
        if(uf_par[x] == x) return x;
        int r = compress(uf_par[x]);
        if(semi[m[x]] > semi[m[uf_par[x]]]) m[x] = m[uf_par[x]];
        return uf_par[x] = r;
    }

    int eval(int x){
        compress(x);
        return m[x];
    }


    void dfs(int x, int &cur){
        semi[x] = cur;
        ord[cur++] = x;
        for (auto &&i : G[x]) {
            if(!~semi[i]){
                par[i] = x;
                dfs(i, cur);
            }
        }
    }
public:
    DominatorTree(int n) : n(n), G(n), Grev(n), idom(n), semi(n), ord(n), par(n), uf_par(n), m(n), tmp(n), U(n) {}

    vector<vector<int>> G, Grev, tmp;
    vector<int> semi, ord, par, uf_par, m, U, idom;

    void add_edge(int a, int b){
        G[a].emplace_back(b);
        Grev[b].emplace_back(a);
    }
    void build(int root){
        for (int i = 0; i < n; ++i) uf_par[i] = i, m[i] = i, semi[i] = -1;
        int cur = 0;
        dfs(root, cur);
        for (int i = n-1; i > 0; --i) {
            int a = ord[i];
            for (auto &&b : Grev[a]) {
                int c = eval(b);
                semi[a] = min(semi[a], semi[c]);
            }
            tmp[ord[semi[a]]].emplace_back(a);
            for (auto &&b : tmp[par[a]]) U[b] = eval(b);
            tmp[par[a]].clear();
            unite(par[a], a);
        }
        for (int i = 1; i < n; ++i) {
            int a = ord[i], b = U[a];
            if(semi[a] == semi[b]) idom[a] = semi[a];
            else idom[a] = semi[b];
        }
        for (int i = 1; i < n; ++i) {
            int a = ord[i];
            idom[a] = ord[idom[a]];
        }
        idom[root] = -1;
    }

};

int main() {
    int n, m;
    cin >> n >> m;
    DominatorTree G(n);
    for (int i = 0; i < m; ++i) {
        int s, t;
        cin >> s >> t;
        s--; t--;
        G.add_edge(s, t);
    }
    G.build(0);
    int q;
    cin >> q;
    for (int i = 0; i < q; ++i) {
        int x;
        cin >> x;
        x--;
        if(!G.idom[x]) cout << x+1 << "\n";
        else cout << G.idom[x]+1 << "\n";
    }
    return 0;
}
accuracy: 0.8571428571428571
time_ms: 270
memory_kb: 22232
final_rank: 15

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005

int N,M;
int root;
int num_visited;
int vertex[SIZE];
int sdom[SIZE],idom[SIZE];
int parent[SIZE],work[SIZE],uf_parent[SIZE];
vector<int> G[SIZE],rev_G[SIZE],bucket[SIZE];

int find(int node_id){
	if(node_id == uf_parent[node_id]){

		return node_id;

	}else{

		int ret = find(uf_parent[node_id]);

		if(sdom[work[node_id]] > sdom[work[uf_parent[node_id]]]){

			work[node_id] = work[uf_parent[node_id]];
		}

		return uf_parent[node_id] = ret;
	}
}

void LINK(int child,int arg_parent){

	uf_parent[child] = arg_parent;
}

void dfs(int node_id,int pre){

	parent[node_id] = pre;
	vertex[num_visited] = node_id;
	sdom[node_id] = num_visited++;

	for(int i = 0; i < G[node_id].size(); i++){

		int next = G[node_id][i];
		if(sdom[next] != -1)continue;

		dfs(next,node_id);
	}
}

int EVAL(int node_id){

	find(node_id);
	return work[node_id];
}


int main(){

	scanf("%d %d",&N,&M);

	int from,to;
	for(int loop = 0; loop < M; loop++){

		scanf("%d %d",&from,&to);
		from--;
		to--;
		G[from].push_back(to);
		rev_G[to].push_back(from);
	}

	root = 0;
	num_visited = 0;

	for(int i = 0; i < N; i++){

		sdom[i] = -1;
		uf_parent[i] = i;
		work[i] = i;
	}

	dfs(root,-1);

	for(int i = N-1; i >= 1; i--){

		int node_id = vertex[i];

		for(int k = 0; k < rev_G[node_id].size(); k++){

			int pre_node = rev_G[node_id][k];
			int u = EVAL(pre_node); //分岐の始点を求める
			sdom[node_id] = min(sdom[node_id],sdom[u]);
		}
		bucket[vertex[sdom[node_id]]].push_back(node_id);

		for(int k = 0; k < bucket[parent[node_id]].size(); k++){

			int v = bucket[parent[node_id]][k];
			int u = EVAL(v);

			if(sdom[u] < sdom[v]){

				idom[v] = u;
			}else{

				idom[v] = parent[node_id];
			}
		}
		bucket[parent[node_id]].clear();
		LINK(node_id,parent[node_id]);
	}

	for(int i = 1; i < N; i++){

		int w = vertex[i];

		if(idom[w] != vertex[sdom[w]]){

			idom[w] = idom[idom[w]];
		}
	}
	idom[root] = -1;

	int num_query;
	scanf("%d",&num_query);

	int tmp;

	for(int loop = 0; loop < num_query; loop++){

		scanf("%d",&tmp);
		tmp--;

		if(idom[tmp] == root){

			printf("%d\n",tmp+1);
		}else{

			printf("%d\n",idom[tmp]+1);
		}
	}

	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 22480
final_rank: 1

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005

int N,M;
int root;
int num_visited;
int vertex[SIZE];
int semi[SIZE],dom[SIZE];
int parent[SIZE],work[SIZE],uf_parent[SIZE];
vector<int> G[SIZE],rev_G[SIZE],bucket[SIZE];

int find(int x){
	if(x == uf_parent[x]){

		return x;

	}else{

		int ret = find(uf_parent[x]);

		if(semi[work[x]] > semi[work[uf_parent[x]]]){

			work[x] = work[uf_parent[x]];
		}

		return uf_parent[x] = ret;
	}
}

void LINK(int child,int arg_parent){

	uf_parent[child] = arg_parent;
}

void dfs(int node_id,int pre){

	parent[node_id] = pre;
	vertex[num_visited] = node_id;
	semi[node_id] = num_visited++;

	for(int i = 0; i < G[node_id].size(); i++){

		int next = G[node_id][i];
		if(semi[next] != -1)continue;

		dfs(next,node_id);
	}
}

int EVAL(int node_id){

	find(node_id);
	return work[node_id];
}


int main(){

	scanf("%d %d",&N,&M);

	int from,to;
	for(int loop = 0; loop < M; loop++){

		scanf("%d %d",&from,&to);
		from--;
		to--;
		G[from].push_back(to);
		rev_G[to].push_back(from);
	}

	root = 0;
	num_visited = 0;

	for(int i = 0; i < N; i++){

		semi[i] = -1;
		uf_parent[i] = i;
		work[i] = i;
	}

	dfs(root,-1);

	for(int i = N-1; i >= 1; i--){

		int w = vertex[i];

		for(int k = 0; k < rev_G[w].size(); k++){
			int v = rev_G[w][k];
			int u = EVAL(v);
			semi[w] = min(semi[w],semi[u]);
		}
		bucket[vertex[semi[w]]].push_back(w);

		for(int k = 0; k < bucket[parent[w]].size(); k++){

			int v = bucket[parent[w]][k];
			int u = EVAL(v);

			if(semi[u] < semi[v]){

				dom[v] = u;
			}else{

				dom[v] = parent[w];
			}
		}
		bucket[parent[w]].clear();
		LINK(w,parent[w]);
	}

	for(int i = 1; i < N; i++){

		int w = vertex[i];
		if(dom[w] != vertex[semi[w]]){

			dom[w] = dom[dom[w]];
		}
	}
	dom[root] = -1;

	int num_query;
	scanf("%d",&num_query);

	int tmp;

	for(int loop = 0; loop < num_query; loop++){

		scanf("%d",&tmp);
		tmp--;

		if(dom[tmp] == root){

			printf("%d\n",tmp+1);
		}else{

			printf("%d\n",dom[tmp]+1);
		}
	}

	return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 22556
final_rank: 3

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005

int N,M;
int root;
int num_visited;
int vertex[SIZE];
int semi[SIZE],dom[SIZE];
int parent[SIZE],work[SIZE],uf_parent[SIZE];
vector<int> G[SIZE],rev_G[SIZE],bucket[SIZE];

int find(int x){
	if(x == uf_parent[x]){

		return x;

	}else{

		if(semi[work[x]] > semi[work[uf_parent[x]]]){

			work[x] = work[uf_parent[x]];
		}

		return uf_parent[x] = find(uf_parent[x]);
	}
}

void LINK(int child,int arg_parent){

	uf_parent[child] = arg_parent;
}

void dfs(int node_id,int pre){

	parent[node_id] = pre;
	vertex[num_visited] = node_id;
	semi[node_id] = num_visited++;

	for(int i = 0; i < G[node_id].size(); i++){

		int next = G[node_id][i];
		if(semi[next] != -1)continue;

		dfs(next,node_id);
	}
}

int EVAL(int node_id){

	find(node_id);
	return work[node_id];
}


int main(){

	scanf("%d %d",&N,&M);

	int from,to;
	for(int loop = 0; loop < M; loop++){

		scanf("%d %d",&from,&to);
		from--;
		to--;
		G[from].push_back(to);
		rev_G[to].push_back(from);
	}

	root = 0;
	num_visited = 0;

	for(int i = 0; i < N; i++){

		semi[i] = -1;
		uf_parent[i] = i;
		work[i] = i;
	}

	dfs(root,-1);

	for(int i = N-1; i >= 1; i--){

		int w = vertex[i];

		for(int k = 0; k < rev_G[w].size(); k++){
			int v = rev_G[w][k];
			int u = EVAL(v);
			semi[w] = min(semi[w],semi[u]);
		}
		bucket[vertex[semi[w]]].push_back(w);

		for(int k = 0; k < bucket[parent[w]].size(); k++){

			int v = bucket[parent[w]][k];
			int u = EVAL(v);

			if(semi[u] < semi[v]){

				dom[v] = u;
			}else{

				dom[v] = parent[w];
			}
		}
		bucket[parent[w]].clear();
		LINK(w,parent[w]);
	}

	for(int i = 1; i < N; i++){

		int w = vertex[i];
		if(dom[w] != vertex[semi[w]]){

			dom[w] = dom[dom[w]];
		}
	}
	dom[root] = -1;

	int num_query;
	scanf("%d",&num_query);

	int tmp;

	for(int loop = 0; loop < num_query; loop++){

		scanf("%d",&tmp);
		tmp--;

		if(dom[tmp] == root){

			printf("%d\n",tmp+1);
		}else{

			printf("%d\n",dom[tmp]+1);
		}
	}

	return 0;
}
accuracy: 0.8571428571428571
time_ms: 100
memory_kb: 22544
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005

int N,M;
int root;
int num_visited;
int vertex[SIZE];
int semi[SIZE],dom[SIZE];
int parent[SIZE],work[SIZE],uf_parent[SIZE];
vector<int> G[SIZE],rev_G[SIZE],bucket[SIZE];

int find(int x){
	if(x == uf_parent[x]){

		return x;

	}else{

		if(semi[work[x]] > semi[work[uf_parent[x]]]){

			work[x] = work[uf_parent[x]];
		}

		return uf_parent[x] = find(uf_parent[x]);
	}
}

void LINK(int child,int arg_parent){

	uf_parent[child] = arg_parent;
}

void dfs(int node_id,int pre){

	parent[node_id] = pre;
	vertex[num_visited] = node_id;
	semi[node_id] = num_visited++;

	for(int i = 0; i < G[node_id].size(); i++){

		int next = G[node_id][i];
		if(semi[next] != -1)continue;

		dfs(next,node_id);
	}
}

int EVAL(int node_id){

	find(node_id);
	return work[node_id];
}


int main(){

	scanf("%d %d",&N,&M);

	int from,to;
	for(int loop = 0; loop < M; loop++){

		scanf("%d %d",&from,&to);
		from--;
		to--;
		G[from].push_back(to);
		rev_G[to].push_back(from);
	}

	root = 0;
	num_visited = 0;

	for(int i = 0; i < N; i++){

		semi[i] = -1;
		uf_parent[i] = i;
		work[i] = i;
	}

	dfs(root,-1);

	for(int i = N-1; i >= 1; i--){

		int w = vertex[i];

		for(int k = 0; k < rev_G[w].size(); k++){
			int v = rev_G[w][k];
			int u = EVAL(v);
			semi[w] = min(semi[w],semi[u]);
		}
		bucket[vertex[semi[w]]].push_back(w);
		LINK(w,parent[w]);

		for(int k = 0; k < bucket[parent[w]].size(); k++){

			int v = bucket[parent[w]][k];
			int u = EVAL(v);

			if(semi[u] < semi[v]){

				dom[v] = u;
			}else{

				dom[v] = parent[w];
			}
		}

		bucket[parent[w]].clear();
	}

	for(int i = 1; i < N; i++){

		int w = vertex[i];
		if(dom[w] != vertex[semi[w]]){

			dom[w] = dom[dom[w]];
		}
	}
	dom[root] = -1;

	int num_query;
	scanf("%d",&num_query);

	int tmp;

	for(int loop = 0; loop < num_query; loop++){

		scanf("%d",&tmp);
		tmp--;

		if(dom[tmp] == root){

			printf("%d\n",tmp+1);
		}else{

			printf("%d\n",dom[tmp]+1);
		}
	}

	return 0;
}
accuracy: 0.8571428571428571
time_ms: 100
memory_kb: 22592
final_rank: 11

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005

int N,M;
int root;
int num_visited;
int vertex[SIZE];
int semi[SIZE],dom[SIZE];
int parent[SIZE],work[SIZE],uf_parent[SIZE];
vector<int> G[SIZE],rev_G[SIZE],bucket[SIZE];

int find(int x){
	if(x == uf_parent[x]){

		return x;

	}else{

		if(semi[work[x]] > semi[work[uf_parent[x]]]){

			work[x] = work[uf_parent[x]];
		}

		return uf_parent[x] = find(uf_parent[x]);
	}
}

void LINK(int child,int arg_parent){

	uf_parent[child] = arg_parent;
}

void dfs(int node_id,int pre){

	parent[node_id] = pre;
	vertex[num_visited] = node_id;
	semi[node_id] = num_visited++;

	for(int i = 0; i < G[node_id].size(); i++){

		int next = G[node_id][i];
		if(semi[next] != -1)continue;

		dfs(next,node_id);
	}
}

int EVAL(int node_id){

	find(node_id);
	return work[node_id];
}


int main(){

	scanf("%d %d",&N,&M);

	int from,to;
	for(int loop = 0; loop < M; loop++){

		scanf("%d %d",&from,&to);
		from--;
		to--;
		G[from].push_back(to);
		rev_G[to].push_back(from);
	}

	root = 0;
	num_visited = 0;

	for(int i = 0; i < N; i++){

		semi[i] = -1;
		uf_parent[i] = i;
		work[i] = i;
	}

	dfs(root,-1);

	for(int i = N-1; i >= 1; i--){

		int w = vertex[i];

		for(int k = 0; k < rev_G[w].size(); k++){
			int v = rev_G[w][k];
			int u = EVAL(v);
			semi[w] = min(semi[w],semi[u]);
		}
		bucket[vertex[semi[w]]].push_back(w);
		LINK(w,parent[w]);

		for(int k = 0; k < bucket[parent[w]].size(); k++){

			int v = bucket[parent[w]][k];
			int u = EVAL(v);

			if(semi[u] < semi[v]){

				dom[v] = u;
			}else{

				dom[v] = parent[w];
			}
		}

		bucket[vertex[semi[w]]].clear();
	}

	for(int i = 1; i < N; i++){

		int w = vertex[i];
		if(dom[w] != vertex[semi[w]]){

			dom[w] = dom[dom[w]];
		}
	}
	dom[root] = -1;

	int num_query;
	scanf("%d",&num_query);

	int tmp;

	for(int loop = 0; loop < num_query; loop++){

		scanf("%d",&tmp);
		tmp--;

		if(dom[tmp] == root){

			printf("%d\n",tmp+1);
		}else{

			printf("%d\n",dom[tmp]+1);
		}
	}

	return 0;
}
accuracy: 0.5714285714285714
time_ms: 30
memory_kb: 14500
final_rank: 19