Problem:
Problem J
Post Office Investigation
In this country, all international mails from abroad are first gathered to the central post office, and then delivered to each destination post office relaying some post offices on the way. The delivery routes between post offices are described by a directed graph $G = (V,E)$, where $V$ is the set of post offices and $E$ is the set of possible mail forwarding steps. Due to the inefficient operations, you cannot expect that the mails are delivered along the shortest route.
The set of post offices can be divided into a certain number of groups. Here, a group is defined as a set of post offices where mails can be forwarded from any member of the group to any other member, directly or indirectly. The number of post offices in such a group does not exceed 10.
The post offices frequently receive complaints from customers that some mails are not delivered yet. Such a problem is usually due to system trouble in a single post office, but identifying which is not easy. Thus, when such complaints are received, the customer support sends staff to check the system of each candidate post office. Here, the investigation cost to check the system of the post office $u$ is given by $c_u$, which depends on the scale of the post office.
Since there are many post offices in the country, and such complaints are frequently received, reducing the investigation cost is an important issue. To reduce the cost, the post service administration determined to use the following scheduling rule: When complaints on undelivered mails are received by the post offices $w_1, ..., w_k$ one day, staff is sent on the next day to investigate a single post office $v$ with the lowest investigation cost among candidates. Here, the post office $v$ is a candidate if all mails from the central post office to the post offices $w_1, ... , w_k$ must go through $v$. If no problem is found in the post office $v$, we have to decide the order of investigating other post offices, but the problem is left to some future days.
Your job is to write a program that finds the cost of the lowest-cost candidate when the list of complained post offices in a day, described by $w_1, ... , w_k$, is given as a query.
Input
The input consists of a single test case, formatted as follows.
$n$ $m$
$u_1$ $v_1$
...
$u_m$ $v_m$
$c_1$
...
$c_n$
$q$
$k_1$ $w_{11}$ ... $w_{1k_1}$
...
$k_q$ $w_{q1}$ ... $w_{qk_q}$
$n$ is the number of post offices $(2 \leq n \leq 50,000)$, which are numbered from 1 to $n$. Here, post office 1 corresponds to the central post office. $m$ is the number of forwarding pairs of post offices $(1 \leq m \leq 100,000)$. The pair, $u_i$ and $v_i$, means that some of the mails received at post office $u_i$ are forwarded to post office $v_i$ $(i = 1, ..., m)$. $c_j$ is the investigation cost for the post office $j$ $(j = 1,  ..., n, 1 \leq c_j \leq 10^9)$. $q$ $(q \geq 1)$ is the number of queries, and each query is specified by a list of post offices which received un
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

using namespace std;

using vi = vector<int>;

const int mxn = 50006;

namespace DominatorTree {
	int dfn[mxn], pre[mxn], pt[mxn], sz;
	int semi[mxn], dsu[mxn], idom[mxn], best[mxn];
	int get(int x) {
		if (x == dsu[x]) return x;
		int y = get(dsu[x]);
		if (semi[best[x]] > semi[best[dsu[x]]]) best[x] = best[dsu[x]];
		return dsu[x] = y;
	}
	void dfs(int u, const vi succ[]) {
		dfn[u] = sz; pt[sz++] = u;
		for (auto &v: succ[u]) if (!~dfn[v]) {
			dfs(v, succ); pre[dfn[v]] = dfn[u];
		}
	}
	void tarjan(const vi pred[], vi dom[]) {
		for (int j = sz - 1, u; u = pt[j], j > 0; --j) {
			for (auto &tv : pred[u]) if (~dfn[tv]) {
				int v = dfn[tv]; get(v);
				if (semi[best[v]] < semi[j]) semi[j] = semi[best[v]];
			}
			dom[semi[j]].push_back(j);
			int x = dsu[j] = pre[j];
			for (auto &z : dom[x]) {
				get(z);
				if (semi[best[z]] < x) idom[z] = best[z];
				else idom[z] = x;
			}
			dom[x].clear();
		}
		for (int i = 1; i < sz; ++i) {
			if (semi[i] != idom[i]) idom[i] = idom[idom[i]];
			dom[idom[i]].push_back(i);
		}
	}
	void build(int n, int s, const vi succ[], const vi pred[], vi dom[]) {
		for (int i = 0; i < n; ++i) {
			dfn[i] = -1; dom[i].clear();
			dsu[i] = best[i] = semi[i] = i;
		}
		sz = 0; dfs(s, succ); tarjan(pred, dom);
	}
}

vi pred[mxn], succ[mxn], dom[mxn];

int n, m;
int f[mxn];

#define e dom

struct LCA {
	int h[mxn];
	int a[mxn][20];
	void dfs(int x, int p) {
		h[x] = h[p] + 1;
		a[x][0] = p;
		f[x] = min(f[x], f[p]);
		for (int i = 1; i < 20; ++i)
			a[x][i] = a[a[x][i - 1]][i - 1];
		for (auto i : e[x - 1])
			dfs(i + 1, x);
	}
	int lca(int x, int y) {
		for (int i = 20; i--; )
			if (h[a[x][i]] >= h[y])
				x = a[x][i];
			else if (h[a[y][i]] >= h[x])
				y = a[y][i];
		if (x == y)
			return x;
		for (int i = 20; i--; ) if (a[x][i] != a[y][i]) {
			x = a[x][i];
			y = a[y][i];
		}
		return a[x][0];
	}
} Q;

int main() {
	cin >> n >> m;
	for (int i = 0; i < m; ++i) {
		int x, y;
		scanf("%d%d", &x, &y);
		--x; --y;
		succ[x].push_back(y);
		pred[y].push_back(x);
	}
	DominatorTree::build(n, 0, succ, pred, dom);
	
	/*for (int i = 0; i < n; ++i) {
		cout << i << " " << DominatorTree::dfn[i] << ": ";
		for (auto j : dom[i])
			cout << j << ' ';
		cout << endl;
	}*/
	
	for (int i = 0; i < n; ++i)
		scanf("%d", &f[DominatorTree::dfn[i] + 1]);
	f[0] = 0x3f3f3f3f;
	
	Q.dfs(1, 0);
	
	int q;
	cin >> q;
	while (q--) {
		int t;
		scanf("%d", &t);
		vector<int> v;
		while (t--) {
			int t2;
			scanf("%d", &t2);
			--t2;
			t2 = DominatorTree::dfn[t2] + 1;
			v.push_back(t2);
		}
		int o = v[0];
		for (int i = 1; i < v.size(); ++i)
			o = Q.lca(o, v[i]);
		printf("%d\n", f[o]);
	}
	
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 19664
final_rank: 1

code_snippet: #include <bits/stdc++.h>

using namespace std;

using vi = vector<int>;

const int mxn = 50006;

namespace DominatorTree {
	int dfn[mxn], pre[mxn], pt[mxn], sz;
	int semi[mxn], dsu[mxn], idom[mxn], best[mxn];
	int get(int x) {
		if (x == dsu[x]) return x;
		int y = get(dsu[x]);
		if (semi[best[x]] > semi[best[dsu[x]]]) best[x] = best[dsu[x]];
		return dsu[x] = y;
	}
	void dfs(int u, const vi succ[]) {
		dfn[u] = sz; pt[sz++] = u;
		for (auto &v: succ[u]) if (!~dfn[v]) {
			dfs(v, succ); pre[dfn[v]] = dfn[u];
		}
	}
	void tarjan(const vi pred[], vi dom[]) {
		for (int j = sz - 1, u; u = pt[j], j > 0; --j) {
			for (auto &tv : pred[u]) if (~dfn[tv]) {
				int v = dfn[tv]; get(v);
				if (semi[best[v]] < semi[j]) semi[j] = semi[best[v]];
			}
			dom[semi[j]].push_back(j);
			int x = dsu[j] = pre[j];
			for (auto &z : dom[x]) {
				get(z);
				if (semi[best[z]] < x) idom[z] = best[z];
				else idom[z] = x;
			}
			dom[x].clear();
		}
		for (int i = 1; i < sz; ++i) {
			if (semi[i] != idom[i]) idom[i] = idom[idom[i]];
			dom[idom[i]].push_back(i);
		}
	}
	void build(int n, int s, const vi succ[], const vi pred[], vi dom[]) {
		for (int i = 0; i < n; ++i) {
			dfn[i] = -1; dom[i].clear();
			dsu[i] = best[i] = semi[i] = i;
		}
		sz = 0; dfs(s, succ); tarjan(pred, dom);
	}
}

vi pred[mxn], succ[mxn], dom[mxn];

int n, m;
int f[mxn];

#define e dom

struct LCA {
	int h[mxn];
	int a[mxn][20];
	void dfs(int x, int p) {
		h[x] = h[p] + 1;
		a[x][0] = p;
		if (p != -1)
			f[x] = min(f[x], f[p]);
		for (int i = 1; i < 20; ++i)
			a[x][i] = a[a[x][i - 1]][i - 1];
		for (auto i : e[x])
			dfs(i, x);
	}
	int lca(int x, int y) {
		for (int i = 20; i--; )
			if (h[a[x][i]] >= h[y])
				x = a[x][i];
			else if (h[a[y][i]] >= h[x])
				y = a[y][i];
		if (x == y)
			return x;
		for (int i = 20; i--; ) if (a[x][i] != a[y][i]) {
			x = a[x][i];
			y = a[y][i];
		}
		return a[x][0];
	}
} Q;

int main() {
	cin >> n >> m;
	for (int i = 0; i < m; ++i) {
		int x, y;
		scanf("%d%d", &x, &y);
		--x; --y;
		succ[x].push_back(y);
		pred[y].push_back(x);
	}
	DominatorTree::build(n, 0, succ, pred, dom);
	
	/*for (int i = 0; i < n; ++i) {
		cout << i << " " << DominatorTree::dfn[i] << ": ";
		for (auto j : dom[i])
			cout << j << ' ';
		cout << endl;
	}*/
	
	for (int i = 0; i < n; ++i)
		scanf("%d", &f[DominatorTree::dfn[i]]);
	
	Q.dfs(0, -1);
	
	int q;
	cin >> q;
	while (q--) {
		int t;
		scanf("%d", &t);
		vector<int> v;
		while (t--) {
			int t2;
			scanf("%d", &t2);
			--t2;
			t2 = DominatorTree::dfn[t2];
			v.push_back(t2);
		}
		int o = v[0];
		for (int i = 1; i < v.size(); ++i)
			o = Q.lca(o, v[i]);
		printf("%d\n", f[o]);
	}
	
	return 0;
}
accuracy: 0.2857142857142857
time_ms: 30
memory_kb: 17300
final_rank: 14

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 50005

int N,M;
int root;
int COST[SIZE],in_num[SIZE],minimum[SIZE];

//支配木
int num_visited;
int vertex[SIZE];
int sdom[SIZE],idom[SIZE];
int dom_parent[SIZE],work[SIZE],uf_parent[SIZE];
vector<int> dom_G[SIZE],dom_rev_G[SIZE],bucket[SIZE];

//LCA
int MAX_LOG_V = 17;
int POW[18];
int parent[18][SIZE];
int depth[SIZE];
vector<int> G[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 dom_dfs(int node_id,int pre){

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

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

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

		dom_dfs(next,node_id);
	}
}

int EVAL(int node_id){

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



//parentとdepthを再帰的に設定
void dfs(int node_id,int parent_id,int d){
	parent[0][node_id] = parent_id;
	depth[node_id] = d;
	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i] != parent_id)dfs(G[node_id][i],node_id,d+1);
	}
}

//初期化
void init(){
	//parent[0]とdepthを初期化する
	dfs(root,-1,0);
	//parentを初期化する
	for(int k = 0; k + 1 < MAX_LOG_V; k++){
		for(int node_id = 0; node_id < N; node_id++){
			if(parent[k][node_id] < 0)parent[k+1][node_id] = -1; //node_idの2^k上のノードがルートノードより上なら、2^(k+1)上も同様とする
			else{
				parent[k+1][node_id] = parent[k][parent[k][node_id]];
			}
		}
	}
}

//leftとrightのLCAを求める
int lca(int left,int right){
	//leftとrightの深さが同じになるまで親を辿る
	if(depth[left] > depth[right])swap(left,right); //rightの方が深い所にいる

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(depth[right]-depth[left] >= POW[k]){ //たとえば深さの差が39なら、32+4+2+1のように、ノードを上方に移動させる
			right = parent[k][right];
		}
	}

	if(left == right)return left;

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(parent[k][left] == parent[k][right]){
			//Do nothing
		}else{
			left = parent[k][left];
			right = parent[k][right];
		}
	}
	return parent[0][left]; //最後は、leftの親とrightの親が必ず一致している
}

//idomグラフ上の、自分を含めた先祖の最小コストを求める
void recursive(int node_id){

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

		int child = G[node_id][i];

		minimum[child] = min(minimum[child],minimum[node_id]);
		recursive(child);
	}
}


int main(){

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

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

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

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

		scanf("%d",&COST[i]);
	}

	root = 0;
	num_visited = 0;

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

		sdom[i] = -1; //半支配節
		uf_parent[i] = i; //経路圧縮用配列
		work[i] = i; //仮sdom
	}

	dom_dfs(root,-1);

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

		int node_id = vertex[i];

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

			int pre_node = dom_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[dom_parent[node_id]].size(); k++){

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

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

				idom[v] = u;
			}else{

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

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

		in_num[i] = 0;
	}

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

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

			idom[w] = idom[idom[w]];
		}
		G[idom[w]].push_back(w); //idomの有向グラフを作る
	}

	POW[0] = 1;
	for(int i = 1; i <= 17; i++){

		POW[i] = POW[i-1]*2;
	}

	init();

	minimum[root] = COST[root];
	for(int i = 1;i < N; i++){

		minimum[i] = COST[i];
	}

	recursive(root);

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

	int tmp;
	int LCA,tmp_node;

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

		scanf("%d",&tmp);

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

		if(tmp == 1){

			printf("%d\n",minimum[tmp_node]);

		}else{

			LCA = tmp_node;
			for(int i = 1; i < tmp; i++){

				scanf("%d",&tmp_node);
				tmp_node--;
				LCA = lca(LCA,tmp_node); //idomグラフ上でのlcaを求める
			}
			printf("%d\n",minimum[LCA]);
		}
	}

	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 21784
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 5;

namespace dominator {
vector<int> g[maxn], r[maxn], rdom[maxn];
int dfn[maxn], rev[maxn], fa[maxn], sdom[maxn], dom[maxn], val[maxn], rp[maxn], tk;
void init(int n) {
    // vertices are numbered from 0 to n - 1
    fill(dfn, dfn + n, -1);
    fill(rev, rev + n, -1);
    fill(fa, fa + n, -1);
    fill(val, val + n, -1);
    fill(sdom, sdom + n, -1);
    fill(rp, rp + n, -1);
    fill(dom, dom + n, -1);
    tk = 0;
    for (int i = 0; i < n; ++i)
        g[i].clear();
}
void add_edge(int x, int y) {
    g[x].push_back(y);
}
void dfs(int x) {
    rev[dfn[x] = tk] = x;
    fa[tk] = sdom[tk] = val[tk] = tk;
    tk++;
    for (int &u : g[x]) {
        if (dfn[u] == -1) dfs(u), rp[dfn[u]] = dfn[x];
        r[dfn[u]].push_back(dfn[x]);
    } 
}
void merge(int x, int y) {
    fa[x] = y;
}
int find(int x, int c = 0) {
    if (fa[x] == x) return c ? -1 : x;
    int p = find(fa[x], 1);
    if (p == -1) return c ? fa[x] : val[x];
    if (sdom[val[x]] > sdom[val[fa[x]]]) val[x] = val[fa[x]];
    fa[x] = p;
    return c ? p : val[x];
}
vector<int> build(int s, int n) {
    // return the father of each node in the dominator tree
    dfs(s);
    for (int i = tk - 1; i >= 0; --i) {
        for (int &u : r[i]) sdom[i] = min(sdom[i], sdom[find(u)]);
        if (i) rdom[sdom[i]].push_back(i);
        for (int &u : rdom[i]) {
            int p = find(u);
            if (sdom[p] == i) dom[u] = i;
            else dom[u] = p;
        }
        if (i) merge(i, rp[i]);
    }
    vector<int> p(n, -1);
    for (int i = 1; i < tk; ++i) if (sdom[i] != dom[i]) dom[i] = dom[dom[i]];
    for (int i = 1; i < tk; ++i) p[rev[i]] = rev[dom[i]];
    return p;
}}

int c[maxn], dep[maxn], fa[maxn][20];
vector<int> g[maxn];

void dfs(int x, int p) {
    fa[x][0] = p;
    dep[x] = ~p ? dep[p] + 1 : 0;
    if (p != -1) c[x] = min(c[x], c[p]);
    for (int i = 1; (1 << i) <= dep[x]; ++i)
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
    for (int u : g[x]) dfs(u, x);
}

int lca(int x, int y) {
    if (dep[x] > dep[y]) swap(x, y);
    for (int i = 0; i < 20; ++i) {
        if ((dep[y] - dep[x]) >> i & 1)
            y = fa[y][i];
    }
    if (x == y) return x;
    for (int i = 19; i >= 0; --i) {
        if (fa[x][i] != fa[y][i]) {
            x = fa[x][i];
            y = fa[y][i];
        }
    }
    return fa[x][0];
}

int main() {
    int n, m; scanf("%d%d", &n, &m);
    dominator::init(n);
    for (int i = 0; i < m; ++i) {
        int u, v; scanf("%d%d", &u, &v);
        --u, --v;
        dominator::add_edge(u, v);
    }
    for (int i = 0; i < n; ++i) scanf("%d", &c[i]);
    auto p = dominator::build(0, n);
    assert(p[0] == -1);
    for (int i = 1; i < n; ++i) g[p[i]].push_back(i);
    dfs(0, -1);
    int q; scanf("%d", &q);
    while (q--) {
        int k; scanf("%d", &k);
        int z = -1;
        for (int i = 0; i < k; ++i) {
            int w; scanf("%d", &w);
            --w;
            if (z == -1) z = w;
            else z = lca(z, w);
        }
        printf("%d\n", c[z]);
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 26792
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 5;

namespace dominator {
vector<int> g[maxn], r[maxn], rdom[maxn];
int dfn[maxn], rev[maxn], fa[maxn], sdom[maxn], dom[maxn], val[maxn], rp[maxn], tk;
void init(int n) {
    // vertices are numbered from 0 to n - 1
    fill(dfn, dfn + n, -1);
    fill(rev, rev + n, -1);
    fill(fa, fa + n, -1);
    fill(val, val + n, -1);
    fill(sdom, sdom + n, -1);
    fill(rp, rp + n, -1);
    fill(dom, dom + n, -1);
    tk = 0;
    for (int i = 0; i < n; ++i)
        g[i].clear();
}
void add_edge(int x, int y) {
    g[x].push_back(y);
}
void dfs(int x) {
    rev[dfn[x] = tk] = x;
    fa[tk] = sdom[tk] = val[tk] = tk;
    tk++;
    for (int &u : g[x]) {
        if (dfn[u] == -1) dfs(u), rp[dfn[u]] = dfn[x];
        r[dfn[u]].push_back(dfn[x]);
    } 
}
void merge(int x, int y) {
    fa[x] = y;
}
int find(int x, int c = 0) {
    if (fa[x] == x) return x;
    int p = find(fa[x], 1);
    if (p == -1) return c ? fa[x] : val[x];
    if (sdom[val[x]] > sdom[val[fa[x]]]) val[x] = val[fa[x]];
    fa[x] = p;
    return c ? p : val[x];
}
vector<int> build(int s, int n) {
    // return the father of each node in the dominator tree
    dfs(s);
    for (int i = tk - 1; i >= 0; --i) {
        for (int &u : r[i]) sdom[i] = min(sdom[i], sdom[find(u)]);
        if (i) rdom[sdom[i]].push_back(i);
        for (int &u : rdom[i]) {
            int p = find(u);
            if (sdom[p] == i) dom[u] = i;
            else dom[u] = p;
        }
        if (i) merge(i, rp[i]);
    }
    vector<int> p(n, -1);
    for (int i = 1; i < tk; ++i) if (sdom[i] != dom[i]) dom[i] = dom[dom[i]];
    for (int i = 1; i < tk; ++i) p[rev[i]] = rev[dom[i]];
    return p;
}}

int c[maxn], dep[maxn], fa[maxn][20];
vector<int> g[maxn];

void dfs(int x, int p) {
    fa[x][0] = p;
    dep[x] = ~p ? dep[p] + 1 : 0;
    if (p != -1) c[x] = min(c[x], c[p]);
    for (int i = 1; (1 << i) <= dep[x]; ++i)
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
    for (int u : g[x]) dfs(u, x);
}

int lca(int x, int y) {
    if (dep[x] > dep[y]) swap(x, y);
    for (int i = 0; i < 20; ++i) {
        if ((dep[y] - dep[x]) >> i & 1)
            y = fa[y][i];
    }
    if (x == y) return x;
    for (int i = 19; i >= 0; --i) {
        if (fa[x][i] != fa[y][i]) {
            x = fa[x][i];
            y = fa[y][i];
        }
    }
    return fa[x][0];
}

int main() {
    int n, m; scanf("%d%d", &n, &m);
    dominator::init(n);
    for (int i = 0; i < m; ++i) {
        int u, v; scanf("%d%d", &u, &v);
        --u, --v;
        dominator::add_edge(u, v);
    }
    for (int i = 0; i < n; ++i) scanf("%d", &c[i]);
    auto p = dominator::build(0, n);
    assert(p[0] == -1);
    for (int i = 1; i < n; ++i) g[p[i]].push_back(i);
    dfs(0, -1);
    int q; scanf("%d", &q);
    while (q--) {
        int k; scanf("%d", &k);
        int z = -1;
        for (int i = 0; i < k; ++i) {
            int w; scanf("%d", &w);
            --w;
            if (z == -1) z = w;
            else z = lca(z, w);
        }
        printf("%d\n", c[z]);
    }
    return 0;
}
accuracy: 0.6071428571428571
time_ms: 40
memory_kb: 26844
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int maxn = 50000 + 5;
vector<int> g[maxn], r[maxn], tr[maxn], dg[maxn], tz;
int scc[maxn], c[maxn];
bool v[maxn];

namespace dominator {

vector<int> g[maxn], r[maxn], rdom[maxn];
int dfn[maxn], rev[maxn], fa[maxn], sdom[maxn], dom[maxn], val[maxn], rp[maxn], tk;

void init(int n) {
    fill(dfn, dfn + n, -1);
    fill(rev, rev + n, -1);
    fill(fa, fa + n, -1);
    fill(val, val + n, -1);
    fill(sdom, sdom + n, -1);
    fill(rp, rp + n, -1);
    fill(dom, dom + n, -1);
    tk = 0;
    for (int i = 0; i < n; ++i) g[i].clear();
}

void add_edge(int x, int y) {
    g[x].push_back(y);
}

void dfs(int x) {
    rev[dfn[x] = tk] = x;
    fa[tk] = sdom[tk] = val[tk] = tk;
    tk++;
    for (int u : g[x]) {
        if (dfn[u] == -1) dfs(u), rp[dfn[u]] = dfn[x];
        r[dfn[u]].push_back(dfn[x]);
    }
}

void merge(int x, int y) {
    fa[x] = y;
}

int find(int x, int c = 0) {
    if (fa[x] == x) return x;
    int p = find(fa[x], 1);
    if (p == -1) return c ? fa[x] : val[x];
    if (sdom[val[x]] > sdom[val[fa[x]]]) val[x] = val[fa[x]];
    fa[x] = p;
    return c ? p : val[x];
}

vector<int> build(int s, int n) {
    dfs(s);
    for (int i = tk - 1; i >= 0; --i) {
        for (int u : r[i]) sdom[i] = min(sdom[i], sdom[find(u)]);
        if (i) rdom[sdom[i]].push_back(i);
        for (int u : rdom[i]) {
            int p = find(u);
            if (sdom[p] == i) dom[u] = i;
            else dom[u] = p;
        }
        if (i) merge(i, rp[i]);
    }
    vector<int> p(n, -1);
    for (int i = 1; i < tk; ++i) if (sdom[i] != dom[i]) dom[i] = dom[dom[i]];
    for (int i = 1; i < tk; ++i) p[rev[i]] = rev[dom[i]];
    return p;
}

}

int fa[maxn][20], dep[maxn];

void dfs(int x, int p) {
    fa[x][0] = p;
    dep[x] = ~p ? dep[p] + 1 : 0;
    if (~p) c[x] = min(c[x], c[p]);
    for (int i = 1; (1 << i) <= dep[x]; ++i)
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
    for (int u : g[x]) dfs(u, x);
}

int lca(int x, int y) {
    if (dep[x] > dep[y]) swap(x, y);
    for (int i = 0; i < 20; ++i) {
        if ((dep[y] - dep[x]) >> i & 1)
            y = fa[y][i];
    }
    if (y == x) return x;
    for (int i = 19; i >= 0; --i) {
        if (fa[x][i] != fa[y][i]) {
            x = fa[x][i];
            y = fa[y][i];
        }
    }
    return fa[x][0];
}

int main() {
    int n, m; scanf("%d%d", &n, &m);
    dominator::init(n);
    for (int i = 0; i < m; ++i) {
        int u, v; scanf("%d%d", &u, &v);
        --u, --v;
        dominator::add_edge(u, v);
    }
    for (int i = 0; i < n; ++i) scanf("%d", &c[i]);
    vector<int> p = dominator::build(0, n);
    for (int i = 1; i < n; ++i) {
        g[p[i]].push_back(i);
    }
    dfs(0, -1);
    int q; scanf("%d", &q);
    for (int i = 0; i < q; ++i) {
        int k; scanf("%d", &k);
        vector<int> w(k);
        for (int j = 0; j < k; ++j) scanf("%d", &w[j]), --w[j];
        int z = w[0];
        for (int j = 1; j < k; ++j) z = lca(z, w[j]);
        printf("%d\n", c[z]);
    }

    return 0;
}
accuracy: 0.6071428571428571
time_ms: 40
memory_kb: 25696
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int maxn = 50000 + 5;
vector<int> g[maxn], r[maxn], tr[maxn], dg[maxn], tz;
int scc[maxn], c[maxn];
bool v[maxn];

namespace dominator {

vector<int> g[maxn], r[maxn], rdom[maxn];
int dfn[maxn], rev[maxn], fa[maxn], sdom[maxn], dom[maxn], val[maxn], rp[maxn], tk;

void init(int n) {
    fill(dfn, dfn + n, -1);
    fill(rev, rev + n, -1);
    fill(fa, fa + n, -1);
    fill(val, val + n, -1);
    fill(sdom, sdom + n, -1);
    fill(rp, rp + n, -1);
    fill(dom, dom + n, -1);
    tk = 0;
    for (int i = 0; i < n; ++i) g[i].clear();
}

void add_edge(int x, int y) {
    g[x].push_back(y);
}

void dfs(int x) {
    rev[dfn[x] = tk] = x;
    fa[tk] = sdom[tk] = val[tk] = tk;
    tk++;
    for (int u : g[x]) {
        if (dfn[u] == -1) dfs(u), rp[dfn[u]] = dfn[x];
        r[dfn[u]].push_back(dfn[x]);
    }
}

void merge(int x, int y) {
    fa[x] = y;
}

int find(int x, int c = 0) {
    if (fa[x] == x) return x;
    int p = find(fa[x], 1);
    if (p == -1) return c ? fa[x] : val[x];
    if (sdom[val[x]] > sdom[val[fa[x]]]) val[x] = val[fa[x]];
    fa[x] = p;
    return c ? p : val[x];
}

vector<int> build(int s, int n) {
    dfs(s);
    for (int i = tk - 1; i >= 0; --i) {
        for (int u : r[i]) sdom[i] = min(sdom[i], sdom[find(u)]);
        if (i) rdom[sdom[i]].push_back(i);
        for (int u : rdom[i]) {
            int p = find(u);
            if (sdom[p] == i) dom[u] = i;
            else dom[u] = p;
        }
        if (i) merge(i, rp[i]);
    }
    vector<int> p(n, -1);
    for (int i = 1; i < tk; ++i) if (sdom[i] != dom[i]) dom[i] = dom[dom[i]];
    for (int i = 1; i < tk; ++i) p[rev[i]] = rev[dom[i]];
    return p;
}

}

void dfs(int x) {
    v[x] = true;
    for (int u : g[x]) {
        if (!v[u]) dfs(u);
    }
    tz.push_back(x);
}

void rdfs(int x, int z) {
    scc[x] = z;
    for (int u : r[x]) {
        if (scc[u] == -1) rdfs(u, z);
    }
}

vector<int> sc[maxn];
vector<int> ig[maxn];

vector<int> init(int n) {
    for (int i = 0; i < n; ++i) {
        if (!v[i]) dfs(i);
    }
    memset(scc, -1, sizeof(scc));
    int s = 0;
    for (int i = n - 1; i >= 0; --i) {
        if (scc[tz[i]] == -1) rdfs(tz[i], s++);
    }
    dominator::init(s);
    for (int i = 0; i < n; ++i) {
        for (int u : g[i]) {
            if (scc[u] != scc[i]) {
                dominator::add_edge(scc[i], scc[u]);
                dg[scc[i]].push_back(scc[u]);
            } else {
                ig[i].push_back(u);
            }
        }
        sc[scc[i]].push_back(i);
    }

    return dominator::build(scc[0], s);
}

int fa[maxn][20], dep[maxn];

void dfs(int x, int p) {
    fa[x][0] = p;
    dep[x] = ~p ? dep[p] + 1 : 0;
    for (int i = 1; (1 << i) <= dep[x]; ++i)
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
    for (int u : tr[x]) dfs(u, x);
}

int lca(int x, int y) {
    if (dep[x] > dep[y]) swap(x, y);
    for (int i = 0; i < 20; ++i) {
        if ((dep[y] - dep[x]) >> i & 1)
            y = fa[y][i];
    }
    if (y == x) return x;
    for (int i = 19; i >= 0; --i) {
        if (fa[x][i] != fa[y][i]) {
            x = fa[x][i];
            y = fa[y][i];
        }
    }
    return fa[x][0];
}

vector<int> og[maxn];
vector<int> dm[maxn];
vector<int> ing[maxn];
int fp[maxn], gp[maxn];

void build(int s) {
    vector<int> od(s);
    iota(od.begin(), od.end(), 0);
    sort(od.begin(), od.end(), [&](int i, int j) { return dep[i] < dep[j]; });
    for (int i = 0; i < s; ++i) {
        int x = od[i];
        gp[x] = fp[x];
        if (fa[x][0] >= 0) gp[x] = min(gp[x], gp[fa[x][0]]);
    }
}

int jump(int x, int d) {
    for (int i = 0; i < 20; ++i) {
        if (d >> i & 1)
            x = fa[x][i];
    }
    return x;
}

bitset<maxn> bs[maxn];

void dfs2(int x) {
    if (v[x]) return;
    v[x] = true;
    bs[x].set(x);
    for (int u : dg[x]) {
        dfs2(u);
        bs[x] |= bs[u];
    }
}

int main() {
    int n, m; scanf("%d%d", &n, &m);
    for (int i = 0; i < m; ++i) {
        int u, v; scanf("%d%d", &u, &v);
        --u, --v;
        g[u].push_back(v);
        r[v].push_back(u);
    }
    for (int i = 0; i < n; ++i) scanf("%d", &c[i]);

    vector<int> p = init(n);
    int s = (int)p.size(), rt = scc[0];
    dfs2(rt);
    assert(p[rt] == -1);
    for (int i = 0; i < s; ++i) {
        if (p[i] >= 0) tr[p[i]].push_back(i);
    }
    dfs(rt, -1);
    for (int i = 0; i < s; ++i) {
        sort(tr[i].begin(), tr[i].end());
        tr[i].resize(unique(tr[i].begin(), tr[i].end()) - tr[i].begin());
    }

    for (int i = 0; i < s; ++i) fp[i] = 2e9;

    for (int i = 0; i < s; ++i) {
        for (int u : sc[i]) {
            // printf("i = %d parent = %d\n", i, p[i]);
            bool f = false;
            for (int k : r[u]) {
                if (scc[k] != i) f = true;
            }
            if (f) ing[i].push_back(u);
            for (int k : g[u]) {
                if (scc[k] == scc[u]) continue;
                // bool b = binary_search(tr[i].begin(), tr[i].end(), scc[k]); 
                for (int z : tr[i]) {
                    if (bs[scc[k]][z]) og[scc[k]].push_back(u);
                }
            }
        }
        if (ing[i].empty()) {
            // printf("i = %d\n", i);
            assert(i == scc[0]);
            ing[i].push_back(0);
        }
        for (int rm : sc[i]) {
            for (int u : sc[i]) v[u] = false;
            queue<int> q;
            for (int u : ing[i]) {
                if (u == rm) continue;
                v[u] = true;
                q.push(u);        
            }
            while (!q.empty()) {
                int x = q.front(); q.pop();
                for (int u : ig[x]) {
                    if (u == rm) continue;
                    if (!v[u]) {
                        v[u] = true;
                        q.push(u);
                    }
                }
            }
            for (int u : tr[i]) {
                bool ct = false;
                for (int k : og[u]) ct |= v[k];
                if (!ct) fp[u] = min(fp[u], c[rm]);
            }
        }
    }

    build(s);

    int q; scanf("%d", &q);
    while (q--) {
        int k; scanf("%d", &k);
        vector<int> w(k);
        for (int i = 0; i < k; ++i) {
            scanf("%d", &w[i]);
            --w[i];
        }
        int z = scc[w[0]];
        for (int i = 1; i < k; ++i) z = lca(z, scc[w[i]]);
        int ans = gp[z];
        vector<int> oug;
        for (int i = 0; i < k; ++i) {
            int d = dep[scc[w[i]]] - dep[z];
            if (d > 0) {
                int g = jump(scc[w[i]], d - 1);
                oug.push_back(g); 
            }
        }
        for (int rm : sc[z]) {
            for (int u : sc[z]) v[u] = false;
            queue<int> q;
            for (int u : ing[z]) if (u != rm) q.push(u), v[u] = true;
            while (!q.empty()) {
                int x = q.front(); q.pop();
                for (int u : ig[x]) {
                    if (u == rm) continue;
                    if (!v[u]) {
                        v[u] = true;
                        q.push(u);
                    }
                }
            }
            bool cand = true;
            for (int i = 0; i < k; ++i) {
                if (scc[w[i]] == z) cand &= !v[w[i]];
            }
            for (int i : oug) {
                for (int u : og[i]) cand &= !v[u];
            }
            if (cand) {
                ans = min(ans, c[rm]);
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
accuracy: 0.6964285714285714
time_ms: 1570
memory_kb: 39148
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 5;
vector<int> g[maxn], r[maxn], tr[maxn], tz;
int scc[maxn], c[maxn];
bool v[maxn];

namespace dominator {

vector<int> g[maxn], r[maxn], rdom[maxn];
int dfn[maxn], rev[maxn], fa[maxn], sdom[maxn], dom[maxn], val[maxn], rp[maxn], tk;

void init(int n) {
    fill(dfn, dfn + n, -1);
    fill(rev, rev + n, -1);
    fill(fa, fa + n, -1);
    fill(val, val + n, -1);
    fill(sdom, sdom + n, -1);
    fill(rp, rp + n, -1);
    fill(dom, dom + n, -1);
    tk = 0;
    for (int i = 0; i < n; ++i) g[i].clear();
}

void add_edge(int x, int y) {
    g[x].push_back(y);
}

void dfs(int x) {
    rev[dfn[x] = tk] = x;
    fa[tk] = sdom[tk] = val[tk] = tk;
    tk++;
    for (int u : g[x]) {
        if (dfn[u] == -1) dfs(u), rp[dfn[u]] = dfn[x];
        r[dfn[u]].push_back(dfn[x]);
    }
}

void merge(int x, int y) {
    fa[x] = y;
}

int find(int x, int c = 0) {
    if (fa[x] == x) return x;
    int p = find(fa[x], 1);
    if (p == -1) return c ? fa[x] : val[x];
    if (sdom[val[x]] > sdom[val[fa[x]]]) val[x] = val[fa[x]];
    fa[x] = p;
    return c ? p : val[x];
}

vector<int> build(int s, int n) {
    dfs(s);
    for (int i = tk - 1; i >= 0; --i) {
        for (int u : r[i]) sdom[i] = min(sdom[i], sdom[find(u)]);
        if (i) rdom[sdom[i]].push_back(i);
        for (int u : rdom[i]) {
            int p = find(u);
            if (sdom[p] == i) dom[u] = i;
            else dom[u] = p;
        }
        if (i) merge(i, rp[i]);
    }
    vector<int> p(n, -1);
    for (int i = 1; i < tk; ++i) if (sdom[i] != dom[i]) dom[i] = dom[dom[i]];
    for (int i = 1; i < tk; ++i) p[rev[i]] = rev[dom[i]];
    return p;
}

}

void dfs(int x) {
    v[x] = true;
    for (int u : g[x]) {
        if (!v[u]) dfs(u);
    }
    tz.push_back(x);
}

void rdfs(int x, int z) {
    scc[x] = z;
    for (int u : r[x]) {
        if (scc[u] == -1) rdfs(u, z);
    }
}

vector<int> sc[maxn];
vector<int> ig[maxn];

vector<int> init(int n) {
    for (int i = 0; i < n; ++i) {
        if (!v[i]) dfs(i);
    }
    memset(scc, -1, sizeof(scc));
    int s = 0;
    for (int i = n - 1; i >= 0; --i) {
        if (scc[tz[i]] == -1) rdfs(tz[i], s++);
    }
    dominator::init(s);
    for (int i = 0; i < n; ++i) {
        for (int u : g[i]) {
            if (scc[u] != scc[i])
                dominator::add_edge(scc[i], scc[u]);
            else
                ig[i].push_back(u);
        }
        sc[scc[i]].push_back(i);
    }

    return dominator::build(scc[0], s);
}

int fa[maxn][20], dep[maxn];

void dfs(int x, int p) {
    fa[x][0] = p;
    dep[x] = ~p ? dep[p] + 1 : 0;
    for (int i = 1; (1 << i) <= dep[x]; ++i)
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
    for (int u : tr[x]) dfs(u, x);
}

int lca(int x, int y) {
    if (dep[x] > dep[y]) swap(x, y);
    for (int i = 0; i < 20; ++i) {
        if ((dep[y] - dep[x]) >> i & 1)
            y = fa[y][i];
    }
    if (y == x) return x;
    for (int i = 19; i >= 0; --i) {
        if (fa[x][i] != fa[y][i]) {
            x = fa[x][i];
            y = fa[y][i];
        }
    }
    return fa[x][0];
}

vector<int> og[maxn];
vector<int> dm[maxn];
vector<int> ing[maxn];
int fp[maxn], gp[maxn];

void build(int s) {
    vector<int> od(s);
    iota(od.begin(), od.end(), 0);
    sort(od.begin(), od.end(), [&](int i, int j) { return dep[i] < dep[j]; });
    for (int i = 0; i < s; ++i) {
        int x = od[i];
        gp[x] = fp[x];
        if (fa[x][0] >= 0) gp[x] = min(gp[x], gp[fa[x][0]]);
    }
}

int jump(int x, int d) {
    for (int i = 0; i < 20; ++i) {
        if (d >> i & 1)
            x = fa[x][i];
    }
    return x;
}

int main() {
    int n, m; scanf("%d%d", &n, &m);
    for (int i = 0; i < m; ++i) {
        int u, v; scanf("%d%d", &u, &v);
        --u, --v;
        g[u].push_back(v);
        r[v].push_back(u);
    }
    for (int i = 0; i < n; ++i) scanf("%d", &c[i]);

    vector<int> p = init(n);
    int s = (int)p.size(), rt = scc[0];
    for (int i = 0; i < s; ++i) {
        if (p[i] >= 0) tr[p[i]].push_back(i);
    }
    dfs(rt, -1);
    for (int i = 0; i < s; ++i) {
        sort(tr[i].begin(), tr[i].end());
        tr[i].resize(unique(tr[i].begin(), tr[i].end()) - tr[i].begin());
    }

    for (int i = 0; i < s; ++i) fp[i] = 2e9;

    for (int i = 0; i < s; ++i) {
        for (int u : sc[i]) {
            // printf("i = %d parent = %d\n", i, p[i]);
            bool f = false;
            for (int k : r[u]) {
                if (scc[k] != i) f = true;
            }
            if (f) ing[i].push_back(u);
            for (int k : g[u]) {
                if (scc[k] == scc[u]) continue;
                bool b = binary_search(tr[i].begin(), tr[i].end(), scc[k]); 
                if (b) {
                    og[scc[k]].push_back(u);
                    dm[u].push_back(scc[k]);
                }
            }
            if (f) ing[i].push_back(u);
        }
        if (ing[i].empty()) {
            // printf("i = %d\n", i);
            assert(i == scc[0]);
            ing[i].push_back(0);
        }
        for (int rm : sc[i]) {
            for (int u : sc[i]) v[u] = false;
            queue<int> q;
            for (int u : ing[i]) {
                if (u == rm) continue;
                v[u] = true;
                q.push(u);        
            }
            while (!q.empty()) {
                int x = q.front(); q.pop();
                for (int u : ig[x]) {
                    if (u == rm) continue;
                    if (!v[u]) {
                        v[u] = true;
                        q.push(u);
                    }
                }
            }
            for (int u : tr[i]) {
                bool ct = false;
                for (int k : og[u]) ct |= v[k];
                if (!ct) fp[u] = min(fp[u], c[rm]);
            }
        }
    }

    build(s);

    int q; scanf("%d", &q);
    while (q--) {
        int k; scanf("%d", &k);
        vector<int> w(k);
        for (int i = 0; i < k; ++i) {
            scanf("%d", &w[i]);
            --w[i];
        }
        bool same = true;
        for (int i = 0; i < k; ++i) same &= scc[w[i]] == scc[w[0]];
        if (same) {
            int z = scc[w[0]];
            int ans = gp[z]; 
            for (int rm : sc[z]) {
                for (int u : sc[z]) v[u] = false;
                queue<int> q;
                for (int u : ing[z]) if (u != rm) q.push(u), v[u] = true;
                while (!q.empty()) {
                    int x = q.front(); q.pop();
                    for (int u : ig[x]) {
                        if (u == rm) continue;
                        if (!v[u]) {
                            v[u] = true;
                            q.push(u);
                        }
                    }
                }
                bool cand = true;
                for (int i = 0; i < k; ++i) cand &= !v[w[i]];
                if (cand) {
                    ans = min(ans, c[rm]);
                }
            }
            printf("%d\n", ans);
        } else {
            int z = scc[w[0]];
            for (int i = 1; i < k; ++i) z = lca(z, scc[w[i]]);
            int ans = gp[z];
            vector<int> oug;
            for (int i = 0; i < k; ++i) {
                int d = dep[scc[w[i]]] - dep[z];
                if (d > 0) {
                    int g = jump(scc[w[i]], d - 1);
                    oug.push_back(g); 
                }
            }
            for (int rm : sc[z]) {
                for (int u : sc[z]) v[u] = false;
                queue<int> q;
                for (int u : ing[z]) if (u != rm) q.push(u), v[u] = true;
                while (!q.empty()) {
                    int x = q.front(); q.pop();
                    for (int u : ig[x]) {
                        if (u == rm) continue;
                        if (!v[u]) {
                            v[u] = true;
                            q.push(u);
                        }
                    }
                }
                bool cand = true;
                for (int i = 0; i < k; ++i) {
                    if (scc[w[i]] == z) cand &= !v[w[i]];
                }
                for (int i : oug) {
                    for (int u : og[i]) cand &= !v[u];
                }
                if (cand) {
                    ans = min(ans, c[rm]);
                }
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}
accuracy: 0.875
time_ms: 120
memory_kb: 52628
final_rank: 6

code_snippet: // default code for competitive programming
// ver 3.141 {{{

// Includes
#include <bits/stdc++.h>

// Defines
#define NAME(x) #x
#define SZ(c) (int)(c).size()
#define ALL(c) (c).begin(), (c).end()
#define FOR(i, e) for( int i = 0 ; i < (e) ; i++ )
#define ITER(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define REP(i, s, e) for(int i = (s); i <= (e); i++)
#define REPD(i, s, e) for(int i = (s); i >= (e); i--)
#define IOS ios_base::sync_with_stdio( 0 )
#define DEBUG 1
#define fst first
#define snd second
#ifdef ONLINE_JUDGE
#define FILE( fn ) \
    freopen(fn".in","r",stdin); \
    freopen(fn".out","w",stdout);
#else
#define FILE( fn )
#endif

#ifdef AKAI
#define debug( ... ) fprintf( stderr , __VA_ARGS__ )
#else
#define debug( ... )
#endif

using namespace std;

// Typedefs
typedef double real;
typedef long long ll;
typedef pair<ll, int> pli;
typedef tuple<ll, int> tli;
typedef pair<int, int> pii;
typedef tuple<int, int> tii;
typedef unsigned long long ull;

// Some common const.
const double EPS = -1e8;
const double Pi = acos(-1);

// Equal for double
bool inline equ(double a, double b)
{return fabs(a - b) < EPS;}

void RI() {}

template< typename... T >
void RI( int& x , T&... tail )
{
  assert( scanf( "%d" , &x ) == 1 );
  RI( tail... );
}

template< typename Iter , typename F >
inline void out( Iter s , Iter e , F of )
{
  bool flag = 0;
  for( Iter it = s ; it != e ; it++ )
  {
    if( flag ) printf( " " );
    else flag = 1;
    of( *it );
  }
  puts( "" );
}

// }}}
// start ~~QAQ~~

const int MAXN = 100010;
const int LOG  = 22;

struct DominatorTree{
  int n , m , s;
  vector< int > g[ MAXN ] , pred[ MAXN ];
  vector< int > cov[ MAXN ];
  int dfn[ MAXN ] , nfd[ MAXN ] , ts;
  int par[ MAXN ];
  int sdom[ MAXN ] , idom[ MAXN ];

  int mom[ MAXN ] , mn[ MAXN ];

  inline bool cmp( int u , int v )
  { return dfn[ u ] < dfn[ v ]; }

  inline void link( int u , int v )
  { mom[ v ] = u; }

  int eval( int u ){
    if( mom[ u ] == u ) return u;
    int res = eval( mom[ u ] );
    if( cmp( sdom[ mn[ mom[ u ] ] ] , sdom[ mn[ u ] ] ) )
      mn[ u ] = mn[ mom[ u ] ];
    return mom[ u ] = res;
  }

  void init( int _n , int _m , int _s ){
    ts = 0;
    n = _n;
    m = _m;
    s = _s;
    REP( i , 1 , n ) g[ i ].clear() , pred[ i ].clear();
  }
  void addEdge( int u , int v ){
    g[ u ].push_back( v );
    pred[ v ].push_back( u );
  }
  void dfs( int u ){
    ts++;
    dfn[ u ] = ts;
    nfd[ ts ] = u;
    for( int v : g[ u ] ) if( dfn[ v ] == 0 ){
      par[ v ] = u;
      dfs( v );
    }
  }
  void build(){
    REP( i , 1 , n ){
      dfn[ i ] = nfd[ i ] = 0;
      cov[ i ].clear();
      mom[ i ] = mn[ i ] = sdom[ i ] = i;
    }
    dfs( s );
    REPD( i , n , 2 ){
      int u = nfd[ i ];
      for( int v : pred[ u ] ){
        assert( dfn[ v ] != 0 );
        eval( v );
        if( cmp( sdom[ mn[ v ] ] , sdom[ u ] ) )
          sdom[ u ] = sdom[ mn[ v ] ];
      }
      cov[ sdom[ u ] ].push_back( u );
      mom[ u ] = par[ u ];
      for( int w : cov[ par[ u ] ] )
      {
        eval( w );
        if( cmp( sdom[ mn[ w ] ] , par[ u ] ) ) idom[ w ] = mn[ w ];
        else idom[ w ] = par[ u ];
      }
      cov[ par[ u ] ].clear();
    }
    REP( i , 2 , n ){
      int u = nfd[ i ];
      if( idom[ u ] != sdom[ u ] ) idom[ u ] = idom[ idom[ u ] ];
    }
  }
} domT;

int n , m;
int c[ MAXN ];
int dp[ MAXN ];
int dep[ MAXN ];
vector< int > ch[ MAXN ];
int mom[ MAXN ][ LOG ];

void dfs( int u )
{
  for( int v : ch[ u ] )
  {
    dep[ v ] = dep[ u ] + 1;
    dp[ v ] = min( c[ v ] , dp[ u ] );
    dfs( v );
  }
}

inline int lca( int u , int v )
{
  if( dep[ u ] > dep[ v ] ) swap( u , v );
  int diff = dep[ v ] - dep[ u ];
  FOR( i , LOG ) if( diff & ( 1 << i ) )
    v = mom[ v ][ i ];
  if( u == v ) return u;
  REPD( i , LOG-1 , 0 )
    if( mom[ u ][ i ] != mom[ v ][ i ] )
    {
      u = mom[ u ][ i ];
      v = mom[ v ][ i ];
    }
  return mom[ u ][ 0 ];
}

int w[ MAXN ];

int main()
{
  RI( n , m );
  domT.init( n , m , 1 );
  FOR( i , m )
  {
    int u , v;
    RI( u , v );
    domT.addEdge( u , v );
  }
  domT.build();

  REP( i , 1 , n ) RI( c[ i ] );
  REP( i , 1 , n )
  {
    mom[ i ][ 0 ] = domT.idom[ i ];
    ch[ mom[ i ][ 0 ] ].push_back( i );
  }
  REP( j , 1 , LOG-1 ) REP( i , 1 , n )
    mom[ i ][ j ] = mom[ mom[ i ][ j-1 ] ][ j-1 ];

  dp[ 1 ] = c[ 1 ];
  dfs( 1 );

  int q;RI( q );while( q-- )
  {
    int k;RI( k );
    REP( i , 1 , k ) RI( w[ i ] );
    int anc = w[ 1 ];
    REP( i , 2 , k )
      anc = lca( anc , w[ i ] );
    assert( 1 <= anc );
    printf( "%d\n" , dp[ anc ] );
    //int ans = c[ anc ];
    //while( anc )
    //{
      //ans = min( ans , c[ anc ] );
      //anc = mom[ anc ][ 0 ];
    //}
    //printf( "%d\n" , ans );
  }
}
accuracy: 1
time_ms: 70
memory_kb: 26736
final_rank: 4

code_snippet: // default code for competitive programming
// ver 3.141 {{{

// Includes
#include <bits/stdc++.h>

// Defines
#define NAME(x) #x
#define SZ(c) (int)(c).size()
#define ALL(c) (c).begin(), (c).end()
#define FOR(i, e) for( int i = 0 ; i < (e) ; i++ )
#define ITER(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define REP(i, s, e) for(int i = (s); i <= (e); i++)
#define REPD(i, s, e) for(int i = (s); i >= (e); i--)
#define IOS ios_base::sync_with_stdio( 0 )
#define DEBUG 1
#define fst first
#define snd second
#ifdef ONLINE_JUDGE
#define FILE( fn ) \
    freopen(fn".in","r",stdin); \
    freopen(fn".out","w",stdout);
#else
#define FILE( fn )
#endif

#ifdef AKAI
#define debug( ... ) fprintf( stderr , __VA_ARGS__ )
#else
#define debug( ... )
#endif

using namespace std;

// Typedefs
typedef double real;
typedef long long ll;
typedef pair<ll, int> pli;
typedef tuple<ll, int> tli;
typedef pair<int, int> pii;
typedef tuple<int, int> tii;
typedef unsigned long long ull;

// Some common const.
const double EPS = -1e8;
const double Pi = acos(-1);

// Equal for double
bool inline equ(double a, double b)
{return fabs(a - b) < EPS;}

void RI() {}

template< typename... T >
void RI( int& x , T&... tail )
{
  assert( scanf( "%d" , &x ) == 1 );
  RI( tail... );
}

template< typename Iter , typename F >
inline void out( Iter s , Iter e , F of )
{
  bool flag = 0;
  for( Iter it = s ; it != e ; it++ )
  {
    if( flag ) printf( " " );
    else flag = 1;
    of( *it );
  }
  puts( "" );
}

// }}}
// start ~~QAQ~~

const int MAXN = 100010;
const int LOG  = 22;

struct DominatorTree{
  int n , m , s;
  vector< int > g[ MAXN ] , pred[ MAXN ];
  vector< int > cov[ MAXN ];
  int dfn[ MAXN ] , nfd[ MAXN ] , ts;
  int par[ MAXN ];
  int sdom[ MAXN ] , idom[ MAXN ];

  int mom[ MAXN ] , mn[ MAXN ];

  inline bool cmp( int u , int v )
  { return dfn[ u ] < dfn[ v ]; }

  inline void link( int u , int v )
  { mom[ v ] = u; }

  int eval( int u ){
    if( mom[ u ] == u ) return u;
    int res = eval( mom[ u ] );
    if( cmp( sdom[ mn[ mom[ u ] ] ] , sdom[ mn[ u ] ] ) )
      mn[ u ] = mn[ mom[ u ] ];
    return mom[ u ] = res;
  }

  void init( int _n , int _m , int _s ){
    ts = 0;
    n = _n;
    m = _m;
    s = _s;
    REP( i , 1 , n ) g[ i ].clear() , pred[ i ].clear();
  }
  void addEdge( int u , int v ){
    g[ u ].push_back( v );
    pred[ v ].push_back( u );
  }
  void dfs( int u ){
    ts++;
    dfn[ u ] = ts;
    nfd[ ts ] = u;
    for( int v : g[ u ] ) if( dfn[ v ] == 0 ){
      par[ v ] = u;
      dfs( v );
    }
  }
  void build(){
    REP( i , 1 , n ){
      dfn[ i ] = nfd[ i ] = 0;
      cov[ i ].clear();
      mom[ i ] = mn[ i ] = sdom[ i ] = i;
    }
    dfs( s );
    REPD( i , n , 2 ){
      int u = nfd[ i ];
      for( int v : pred[ u ] ){
        assert( dfn[ v ] != 0 );
        eval( v );
        if( cmp( sdom[ mn[ v ] ] , sdom[ u ] ) )
          sdom[ u ] = sdom[ mn[ v ] ];
      }
      cov[ sdom[ u ] ].push_back( u );
      mom[ u ] = par[ u ];
      for( int w : cov[ par[ u ] ] )
      {
        eval( w );
        if( cmp( sdom[ mn[ w ] ] , par[ u ] ) ) idom[ w ] = mn[ w ];
        else idom[ w ] = par[ u ];
      }
      cov[ par[ u ] ].clear();
    }
    REP( i , 2 , n ){
      int u = dfn[ i ];
      if( idom[ u ] != sdom[ u ] ) idom[ u ] = idom[ idom[ u ] ];
    }
  }
} domT;

int n , m;
int c[ MAXN ];
int dp[ MAXN ];
int dep[ MAXN ];
vector< int > ch[ MAXN ];
int mom[ MAXN ][ LOG ];

void dfs( int u )
{
  for( int v : ch[ u ] )
  {
    dep[ v ] = dep[ u ] + 1;
    dp[ v ] = min( c[ v ] , dp[ u ] );
    dfs( v );
  }
}

inline int lca( int u , int v )
{
  if( dep[ u ] > dep[ v ] ) swap( u , v );
  int diff = dep[ v ] - dep[ u ];
  FOR( i , LOG ) if( diff & ( 1 << i ) )
    v = mom[ v ][ i ];
  if( u == v ) return u;
  REPD( i , LOG-1 , 0 )
    if( mom[ u ][ i ] != mom[ v ][ i ] )
    {
      u = mom[ u ][ i ];
      v = mom[ v ][ i ];
    }
  return mom[ u ][ 0 ];
}

int w[ MAXN ];

int main()
{
  RI( n , m );
  domT.init( n , m , 1 );
  FOR( i , m )
  {
    int u , v;
    RI( u , v );
    domT.addEdge( u , v );
  }
  domT.build();

  REP( i , 1 , n ) RI( c[ i ] );
  REP( i , 1 , n )
  {
    mom[ i ][ 0 ] = domT.idom[ i ];
    ch[ mom[ i ][ 0 ] ].push_back( i );
  }
  REP( j , 1 , LOG-1 ) REP( i , 1 , n )
    mom[ i ][ j ] = mom[ mom[ i ][ j-1 ] ][ j-1 ];

  dp[ 1 ] = c[ 1 ];
  dfs( 1 );

  int q;RI( q );while( q-- )
  {
    int k;RI( k );
    REP( i , 1 , k ) RI( w[ i ] );
    int anc = w[ 1 ];
    REP( i , 2 , k )
      anc = lca( anc , w[ i ] );
    int ans = c[ anc ];
    while( anc )
    {
      ans = min( ans , c[ anc ] );
      anc = mom[ anc ][ 0 ];
    }
    printf( "%d\n" , ans );
    //assert( 1 <= anc );
    //printf( "%d\n" , dp[ anc ] );
  }
}
accuracy: 0.7321428571428571
time_ms: 1690
memory_kb: 26624
final_rank: 10

code_snippet: // default code for competitive programming
// ver 3.141 {{{

// Includes
#include <bits/stdc++.h>

// Defines
#define NAME(x) #x
#define SZ(c) (int)(c).size()
#define ALL(c) (c).begin(), (c).end()
#define FOR(i, e) for( int i = 0 ; i < (e) ; i++ )
#define ITER(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define REP(i, s, e) for(int i = (s); i <= (e); i++)
#define REPD(i, s, e) for(int i = (s); i >= (e); i--)
#define IOS ios_base::sync_with_stdio( 0 )
#define DEBUG 1
#define fst first
#define snd second
#ifdef ONLINE_JUDGE
#define FILE( fn ) \
    freopen(fn".in","r",stdin); \
    freopen(fn".out","w",stdout);
#else
#define FILE( fn )
#endif

#ifdef AKAI
#define debug( ... ) fprintf( stderr , __VA_ARGS__ )
#else
#define debug( ... )
#endif

using namespace std;

// Typedefs
typedef double real;
typedef long long ll;
typedef pair<ll, int> pli;
typedef tuple<ll, int> tli;
typedef pair<int, int> pii;
typedef tuple<int, int> tii;
typedef unsigned long long ull;

// Some common const.
const double EPS = -1e8;
const double Pi = acos(-1);

// Equal for double
bool inline equ(double a, double b)
{return fabs(a - b) < EPS;}

void RI() {}

template< typename... T >
void RI( int& x , T&... tail )
{
  assert( scanf( "%d" , &x ) == 1 );
  RI( tail... );
}

template< typename Iter , typename F >
inline void out( Iter s , Iter e , F of )
{
  bool flag = 0;
  for( Iter it = s ; it != e ; it++ )
  {
    if( flag ) printf( " " );
    else flag = 1;
    of( *it );
  }
  puts( "" );
}

// }}}
// start ~~QAQ~~

const int MAXN = 100010;
const int LOG  = 22;

struct DominatorTree{
  int n , m , s;
  vector< int > g[ MAXN ] , pred[ MAXN ];
  vector< int > cov[ MAXN ];
  int dfn[ MAXN ] , nfd[ MAXN ] , ts;
  int par[ MAXN ];
  int sdom[ MAXN ] , idom[ MAXN ];

  int mom[ MAXN ] , mn[ MAXN ];

  inline bool cmp( int u , int v )
  { return dfn[ u ] < dfn[ v ]; }

  inline void link( int u , int v )
  { mom[ v ] = u; }

  int eval( int u ){
    if( mom[ u ] == u ) return u;
    int res = eval( mom[ u ] );
    if( cmp( sdom[ mn[ mom[ u ] ] ] , sdom[ mn[ u ] ] ) )
      mn[ u ] = mn[ mom[ u ] ];
    return mom[ u ] = res;
  }

  void init( int _n , int _m , int _s ){
    ts = 0;
    n = _n;
    m = _m;
    s = _s;
    REP( i , 1 , n ) g[ i ].clear() , pred[ i ].clear();
  }
  void addEdge( int u , int v ){
    g[ u ].push_back( v );
    pred[ v ].push_back( u );
  }
  void dfs( int u ){
    ts++;
    dfn[ u ] = ts;
    nfd[ ts ] = u;
    for( int v : g[ u ] ) if( dfn[ v ] == 0 ){
      par[ v ] = u;
      dfs( v );
    }
  }
  void build(){
    REP( i , 1 , n ){
      dfn[ i ] = nfd[ i ] = 0;
      cov[ i ].clear();
      mom[ i ] = mn[ i ] = sdom[ i ] = i;
    }
    dfs( s );
    REPD( i , n , 2 ){
      int u = nfd[ i ];
      for( int v : pred[ u ] ){
        assert( dfn[ v ] != 0 );
        eval( v );
        if( cmp( sdom[ mn[ v ] ] , sdom[ u ] ) )
          sdom[ u ] = sdom[ mn[ v ] ];
      }
      cov[ sdom[ u ] ].push_back( u );
      mom[ u ] = par[ u ];
      for( int w : cov[ par[ u ] ] )
      {
        eval( w );
        if( cmp( sdom[ mn[ w ] ] , par[ u ] ) ) idom[ w ] = mn[ w ];
        else idom[ w ] = par[ u ];
      }
      cov[ par[ u ] ].clear();
    }
    REP( i , 2 , n ){
      int u = dfn[ i ];
      if( idom[ u ] != sdom[ u ] ) idom[ u ] = idom[ idom[ u ] ];
    }
  }
} domT;

int n , m;
int c[ MAXN ];
int dp[ MAXN ];
int dep[ MAXN ];
vector< int > ch[ MAXN ];
int mom[ MAXN ][ LOG ];

void dfs( int u )
{
  for( int v : ch[ u ] )
  {
    dep[ v ] = dep[ u ] + 1;
    dp[ v ] = min( c[ v ] , dp[ u ] );
    dfs( v );
  }
}

inline int lca( int u , int v )
{
  if( dep[ u ] > dep[ v ] ) swap( u , v );
  int diff = dep[ v ] - dep[ u ];
  FOR( i , LOG ) if( diff & ( 1 << i ) )
    v = mom[ v ][ i ];
  if( u == v ) return u;
  REPD( i , LOG-1 , 0 )
    if( mom[ u ][ i ] != mom[ v ][ i ] )
    {
      u = mom[ u ][ i ];
      v = mom[ v ][ i ];
    }
  return mom[ u ][ 0 ];
}

int w[ MAXN ];

int main()
{
  RI( n , m );
  domT.init( n , m , 1 );
  FOR( i , m )
  {
    int u , v;
    RI( u , v );
    domT.addEdge( u , v );
  }
  domT.build();

  REP( i , 1 , n ) RI( c[ i ] );
  REP( i , 1 , n )
  {
    mom[ i ][ 0 ] = domT.idom[ i ];
    ch[ mom[ i ][ 0 ] ].push_back( i );
  }
  REP( j , 1 , LOG-1 ) REP( i , 1 , n )
    mom[ i ][ j ] = mom[ mom[ i ][ j-1 ] ][ j-1 ];

  dp[ 1 ] = c[ 1 ];
  dfs( 1 );

  int q;RI( q );while( q-- )
  {
    int k;RI( k );
    REP( i , 1 , k ) RI( w[ i ] );
    int anc = w[ 1 ];
    REP( i , 2 , k )
      anc = lca( anc , w[ i ] );
    assert( 1 <= anc );
    printf( "%d\n" , dp[ anc ] );
  }
}
accuracy: 0.7321428571428571
time_ms: 100
memory_kb: 26660
final_rank: 9

code_snippet: // default code for competitive programming
// ver 3.141 {{{

// Includes
#include <bits/stdc++.h>

// Defines
#define NAME(x) #x
#define SZ(c) (int)(c).size()
#define ALL(c) (c).begin(), (c).end()
#define FOR(i, e) for( int i = 0 ; i < (e) ; i++ )
#define ITER(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define REP(i, s, e) for(int i = (s); i <= (e); i++)
#define REPD(i, s, e) for(int i = (s); i >= (e); i--)
#define IOS ios_base::sync_with_stdio( 0 )
#define DEBUG 1
#define fst first
#define snd second
#ifdef ONLINE_JUDGE
#define FILE( fn ) \
    freopen(fn".in","r",stdin); \
    freopen(fn".out","w",stdout);
#else
#define FILE( fn )
#endif

#ifdef AKAI
#define debug( ... ) fprintf( stderr , __VA_ARGS__ )
#else
#define debug( ... )
#endif

using namespace std;

// Typedefs
typedef double real;
typedef long long ll;
typedef pair<ll, int> pli;
typedef tuple<ll, int> tli;
typedef pair<int, int> pii;
typedef tuple<int, int> tii;
typedef unsigned long long ull;

// Some common const.
const double EPS = -1e8;
const double Pi = acos(-1);

// Equal for double
bool inline equ(double a, double b)
{return fabs(a - b) < EPS;}

void RI() {}

template< typename... T >
void RI( int& x , T&... tail )
{
  assert( scanf( "%d" , &x ) == 1 );
  RI( tail... );
}

template< typename Iter , typename F >
inline void out( Iter s , Iter e , F of )
{
  bool flag = 0;
  for( Iter it = s ; it != e ; it++ )
  {
    if( flag ) printf( " " );
    else flag = 1;
    of( *it );
  }
  puts( "" );
}

// }}}
// start ~~QAQ~~

const int MAXN = 100010;
const int LOG  = 22;

struct DominatorTree{
  int n , m , s;
  vector< int > g[ MAXN ] , pred[ MAXN ];
  vector< int > cov[ MAXN ];
  int dfn[ MAXN ] , nfd[ MAXN ] , ts;
  int par[ MAXN ];
  int sdom[ MAXN ] , idom[ MAXN ];

  int mom[ MAXN ] , mn[ MAXN ];

  inline bool cmp( int u , int v )
  { return dfn[ u ] < dfn[ v ]; }

  inline void link( int u , int v )
  { mom[ v ] = u; }

  int eval( int u ){
    if( mom[ u ] == u ) return u;
    int res = eval( mom[ u ] );
    if( cmp( sdom[ mn[ mom[ u ] ] ] , sdom[ mn[ u ] ] ) )
      mn[ u ] = mn[ mom[ u ] ];
    return mom[ u ] = res;
  }

  void init( int _n , int _m , int _s ){
    ts = 0;
    n = _n;
    m = _m;
    s = _s;
    REP( i , 1 , n ) g[ i ].clear() , pred[ i ].clear();
  }
  void addEdge( int u , int v ){
    g[ u ].push_back( v );
    pred[ v ].push_back( u );
  }
  void dfs( int u ){
    ts++;
    dfn[ u ] = ts;
    nfd[ ts ] = u;
    for( int v : g[ u ] ) if( dfn[ v ] == 0 ){
      par[ v ] = u;
      dfs( v );
    }
  }
  void build(){
    REP( i , 1 , n ){
      dfn[ i ] = nfd[ i ] = 0;
      cov[ i ].clear();
      mom[ i ] = mn[ i ] = sdom[ i ] = i;
    }
    dfs( s );
    REPD( i , n , 2 ){
      int u = nfd[ i ];
      for( int v : pred[ u ] ){
        assert( dfn[ v ] != 0 );
        eval( v );
        if( cmp( sdom[ mn[ v ] ] , sdom[ u ] ) )
          sdom[ u ] = sdom[ mn[ v ] ];
      }
      cov[ sdom[ u ] ].push_back( u );
      mom[ u ] = par[ u ];
      for( int w : cov[ par[ u ] ] )
      {
        eval( w );
        if( cmp( sdom[ mn[ w ] ] , par[ u ] ) ) idom[ w ] = mn[ w ];
        else idom[ w ] = par[ u ];
      }
      cov[ par[ u ] ].clear();
    }
    REP( i , 2 , n ){
      int u = dfn[ i ];
      if( idom[ u ] != sdom[ u ] ) idom[ u ] = idom[ idom[ u ] ];
    }
  }
} domT;

int n , m;
int c[ MAXN ];
int dp[ MAXN ];
int dep[ MAXN ];
vector< int > ch[ MAXN ];
int mom[ MAXN ][ LOG ];

void dfs( int u )
{
  for( int v : ch[ u ] )
  {
    dep[ v ] = dep[ u ] + 1;
    dp[ v ] = min( c[ v ] , dp[ u ] );
    dfs( v );
  }
}

inline int lca( int u , int v )
{
  if( dep[ u ] > dep[ v ] ) swap( u , v );
  int diff = dep[ v ] - dep[ u ];
  FOR( i , LOG ) if( diff & ( 1 << i ) )
    v = mom[ v ][ i ];
  if( u == v ) return u;
  REPD( i , LOG-1 , 0 )
    if( mom[ u ][ i ] != mom[ v ][ i ] )
    {
      u = mom[ u ][ i ];
      v = mom[ v ][ i ];
    }
  return mom[ u ][ 0 ];
}

int w[ MAXN ];

int main()
{
  RI( n , m );
  domT.init( n , m , 1 );
  FOR( i , m )
  {
    int u , v;
    RI( u , v );
    domT.addEdge( u , v );
  }
  domT.build();

  REP( i , 1 , n ) RI( c[ i ] );
  REP( i , 1 , n )
  {
    mom[ i ][ 0 ] = domT.idom[ i ];
    ch[ mom[ i ][ 0 ] ].push_back( i );
  }
  REP( j , 1 , LOG-1 ) REP( i , 1 , n )
    mom[ i ][ j ] = mom[ mom[ i ][ j-1 ] ][ j-1 ];

  dp[ 1 ] = c[ 1 ];
  dfs( 1 );

  int q;RI( q );while( q-- )
  {
    int k;RI( k );
    REP( i , 1 , k ) RI( w[ i ] );
    int anc = w[ 1 ];
    REP( i , 2 , k )
      anc = lca( anc , w[ i ] );
    printf( "%d\n" , dp[ anc ] );
  }
}
accuracy: 0.7321428571428571
time_ms: 60
memory_kb: 26748
final_rank: 7

code_snippet: // default code for competitive programming
// ver 3.141 {{{

// Includes
#include <bits/stdc++.h>

// Defines
#define NAME(x) #x
#define SZ(c) (int)(c).size()
#define ALL(c) (c).begin(), (c).end()
#define FOR(i, e) for( int i = 0 ; i < (e) ; i++ )
#define ITER(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define REP(i, s, e) for(int i = (s); i <= (e); i++)
#define REPD(i, s, e) for(int i = (s); i >= (e); i--)
#define IOS ios_base::sync_with_stdio( 0 )
#define DEBUG 1
#define fst first
#define snd second
#ifdef ONLINE_JUDGE
#define FILE( fn ) \
    freopen(fn".in","r",stdin); \
    freopen(fn".out","w",stdout);
#else
#define FILE( fn )
#endif

#ifdef AKAI
#define debug( ... ) fprintf( stderr , __VA_ARGS__ )
#else
#define debug( ... )
#endif

using namespace std;

// Typedefs
typedef double real;
typedef long long ll;
typedef pair<ll, int> pli;
typedef tuple<ll, int> tli;
typedef pair<int, int> pii;
typedef tuple<int, int> tii;
typedef unsigned long long ull;

// Some common const.
const double EPS = -1e8;
const double Pi = acos(-1);

// Equal for double
bool inline equ(double a, double b)
{return fabs(a - b) < EPS;}

void RI() {}

template< typename... T >
void RI( int& x , T&... tail )
{
  assert( scanf( "%d" , &x ) == 1 );
  RI( tail... );
}

template< typename Iter , typename F >
inline void out( Iter s , Iter e , F of )
{
  bool flag = 0;
  for( Iter it = s ; it != e ; it++ )
  {
    if( flag ) printf( " " );
    else flag = 1;
    of( *it );
  }
  puts( "" );
}

// }}}
// start ~~QAQ~~

const int MAXN = 100010;
const int LOG  = 22;

struct DominatorTree{
  int n , m , s;
  vector< int > g[ MAXN ] , pred[ MAXN ];
  vector< int > cov[ MAXN ];
  int dfn[ MAXN ] , nfd[ MAXN ] , ts;
  int par[ MAXN ];
  int sdom[ MAXN ] , idom[ MAXN ];

  int mom[ MAXN ] , mn[ MAXN ];

  inline bool cmp( int u , int v )
  { return dfn[ u ] < dfn[ v ]; }

  inline void link( int u , int v )
  { mom[ v ] = u; }

  int eval( int u ){
    if( mom[ u ] == u ) return u;
    int res = eval( mom[ u ] );
    if( cmp( sdom[ mn[ mom[ u ] ] ] , sdom[ mn[ u ] ] ) )
      mn[ u ] = mn[ mom[ u ] ];
    return mom[ u ] = res;
  }

  void init( int _n , int _m , int _s ){
    n = _n;
    m = _m;
    s = _s;
    REP( i , 1 , n ) g[ i ].clear() , pred[ i ].clear();
  }
  void addEdge( int u , int v ){
    g[ u ].push_back( v );
    pred[ v ].push_back( u );
  }
  void dfs( int u ){
    nfd[ dfn[ u ] = ++ts ] = u;
    for( int v : g[ u ] ) if( !dfn[ v ] ){
      par[ v ] = u;
      dfs( v );
    }
  }
  void build(){
    REP( i , 1 , n ){
      dfn[ i ] = nfd[ i ] = 0;
      cov[ i ].clear();
      mom[ i ] = mn[ i ] = sdom[ i ] = i;
    }
    dfs( s );
    REPD( i , n , 2 ){
      int u = nfd[ i ];
      for( int v : pred[ u ] ){
        eval( v );
        if( cmp( sdom[ mn[ v ] ] , sdom[ u ] ) )
          sdom[ u ] = sdom[ mn[ v ] ];
      }
      cov[ sdom[ u ] ].push_back( u );
      link( par[ u ] , u );
      for( int w : cov[ par[ u ] ] )
      {
        eval( w );
        if( cmp( sdom[ mn[ w ] ] , par[ u ] ) ) idom[ w ] = mn[ w ];
        else idom[ w ] = par[ u ];
      }
      cov[ par[ u ] ].clear();
    }
    REP( i , 1 , n ){
      int u = dfn[ i ];
      if( idom[ u ] != sdom[ u ] ) idom[ u ] = idom[ idom[ u ] ];
    }
  }
} domT;

int n , m;
int c[ MAXN ];
int dp[ MAXN ];
int dep[ MAXN ];
vector< int > ch[ MAXN ];
int mom[ MAXN ][ LOG ];

void dfs( int u )
{
  for( int v : ch[ u ] )
  {
    dep[ v ] = dep[ u ] + 1;
    dp[ v ] = min( c[ v ] , dp[ u ] );
    dfs( v );
  }
}

inline int lca( int u , int v )
{
  if( dep[ u ] > dep[ v ] ) swap( u , v );
  int diff = dep[ v ] - dep[ u ];
  FOR( i , LOG ) if( diff & ( 1 << i ) )
    v = mom[ v ][ i ];
  if( u == v ) return u;
  REPD( i , LOG-1 , 0 )
    if( mom[ u ][ i ] != mom[ v ][ i ] )
    {
      u = mom[ u ][ i ];
      v = mom[ v ][ i ];
    }
  return mom[ u ][ 0 ];
}

int w[ MAXN ];

int main()
{
  RI( n , m );
  domT.init( n , m , 1 );
  FOR( i , m )
  {
    int u , v;
    RI( u , v );
    domT.addEdge( u , v );
  }
  domT.build();

  REP( i , 1 , n ) RI( c[ i ] );
  REP( i , 1 , n )
  {
    mom[ i ][ 0 ] = domT.idom[ i ];
    ch[ mom[ i ][ 0 ] ].push_back( i );
  }
  REP( j , 1 , LOG-1 ) REP( i , 1 , n )
    mom[ i ][ j ] = mom[ mom[ i ][ j-1 ] ][ j-1 ];
  dp[ 1 ] = c[ 1 ];
  dfs( 1 );

  int q;RI( q );while( q-- )
  {
    int k;RI( k );
    REP( i , 1 , k ) RI( w[ i ] );
    int anc = w[ 1 ];
    REP( i , 2 , k )
      anc = lca( anc , w[ i ] );
    printf( "%d\n" , dp[ anc ] );
  }
}
accuracy: 0.7321428571428571
time_ms: 70
memory_kb: 26664
final_rank: 8

code_snippet: #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cassert>
#include <cctype>
#include <stack>
#include <queue>
using namespace std;
typedef long long LL;
const int N = 50005;
const int M = 405;
typedef unsigned long long ULL;
 
int cnt, n;

bool times;

struct Bitset {
    ULL a[M];
    Bitset () {
        memset(a , 0 , sizeof(a));
    }
    Bitset operator & (const Bitset &R) const {
        Bitset res = *this;
        for (int i = 0 ; i < M ; ++ i)
            res.a[i] &= R.a[i];
        return res;
    }
    void set(int x) {
        if (!times) {
            if (x >= 25000)
                return;            
        } else {
            if (x < 25000)
                return;
            x -= 25000;
        }
        a[x >> 6] |= 1ULL << (x & 63);
    }
 
    void Sset() {
        for (int i = 0; i < M; ++i)
            a[i] |= ~0ULL;
    }
 
    int operator == (const Bitset &A) const {
        for (int i = 0; i < M; ++i)
            if (a[i] != A.a[i]) return 0;
        return 1;
    }
 
    int low() {
        for (int i = 0; i < M; ++i) {
            if (a[i] != 0) {
                for (int j = 0; j < 64; ++j)
                    if (a[i] >> j & 1) return (i << 6) | j;  
            }
        }
        return 1 << 30;
    }
 
    void  print() {
        for (int i = 0; i < n; ++i)
            printf("%llu ", a[i >> 6] >> (i & 63) & 1);
        puts("");
    }
} bit[N];
 
int  m , pre[N] , mcnt;
 
struct Edge {
    int y, nex;
}edge[N * 20];
 
int mark[N], dfn[N], color[N];
 
stack<int> sta;
vector<int> top[N];
vector<int> query[N];
bool u[N];
void dfs(int x) {
    static int sum = 0;
    mark[x] = dfn[x] = ++sum;
    sta.push(x); u[x] = 1;
    for (int k = pre[x]; k != -1; k = edge[k].nex){
        int y = edge[k].y;
        if (!dfn[y]) {
            dfs(y);
            mark[x] = min(mark[x], mark[y]);
        } else if (u[y]) {
            mark[x] = min(mark[x], dfn[y]);
        }
    }
    if (mark[x] == dfn[x]) {
        int y = -1;
        ++cnt;
        while (y != x) {
            y = sta.top();
            sta.pop();
            u[y] = 0;
            color[y] = cnt;
            mark[y] = 1 << 30;
            top[cnt].push_back(y);
            //   printf("!!%d %d\n", cnt, y);
        }
    }
}
 
pair<int, int> C[N];
int num[N] , res[N] , Q;
int bo[N];
int m1[N * 10], m2[N * 10];
 
int main() {
 
    // cout << (sizeof(bit) >> 20) << endl;
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; ++i)
        scanf("%d%d", m1 + i, m2 + i);
    for (int i = 0; i < n; ++i) { 
        scanf("%d", &C[i].first);
        C[i].second = i;
    }
    sort(C, C + n);
    for (int i = 0; i < n; ++i) {
        num[C[i].second] = i;
    }
    memset(pre, -1, sizeof(pre));
    for (int i = 0 ; i < m ; ++ i) {
        int x = m1[i], y = m2[i];
        //scanf("%d%d", &x, &y);
        --x;
        --y;
        x = num[x];
        y = num[y];
        //printf("%d    %d\n", x, y);
        edge[mcnt] = (Edge) {y, pre[x]};
        pre[x] = mcnt++;
    }
    for (int i = 0; i < n; ++i)
        if (dfn[i] == 0) dfs(i);
    scanf("%d" , &Q);
    for (int i = 0 ; i < Q ; ++ i) {        
        int K;
        scanf("%d", &K);
        query[i].resize(K);
        for (int j = 0 ; j < K ; ++ j) {
            int x;
            scanf("%d" , &x);
            query[i][j] = num[x - 1];
        }
        res[i] = 1 << 30;
    }
    times = 0;
    for (int i = 0; i < n; ++i) {
        if (i != num[0]) {
            bit[i].Sset();
        }
    }
    bit[num[0]].set(num[0]);
    for (int i = cnt; i > 0; --i) {
        queue<int> que;
        for (int j = 0; j < top[i].size(); ++j) {
            que.push((top[i][j]));
        }
        while (!que.empty()) {
            int x = que.front(); que.pop();
            bo[x] = 0;
            for (int k = pre[x]; k != -1; k = edge[k].nex) {
                int y = edge[k].y;
                if (color[y] != color[x]) continue;
                static Bitset tmp;
                tmp = bit[y];
                bit[y] = bit[y] & bit[x];
                bit[y].set(y);
                if (!(tmp == bit[y]) && !bo[y]) {
                    bo[y] = 1;
                    que.push(y);
                }
            }
        }
        for (int j = 0; j < top[i].size(); ++j) {
            int x = top[i][j];
            for (int k = pre[x]; k != -1; k = edge[k].nex) {
                int y = edge[k].y;                 
                if (color[x] != color[y]) {
                    bit[y] = bit[y] & bit[x];
                    bit[y].set(y);
                }
            }
        }
    }
    for (int i = 0 ; i < Q ; ++ i) {
        int K = query[i].size();
        static Bitset tmp;
        tmp.Sset();
        for (int j = 0; j < K; ++ j) {
            int x = query[i][j];
            tmp = tmp & bit[x];
        }
        res[i] = min(res[i] , tmp.low());
    }

    times = 1;
    for (int i = 0; i < n; ++i) {
        if (i != num[0]) {
            bit[i].Sset();
        }
    }
    bit[num[0]].set(num[0]);
    for (int i = cnt; i > 0; --i) {
        queue<int> que;
        for (int j = 0; j < top[i].size(); ++j) {
            que.push((top[i][j]));
        }
        while (!que.empty()) {
            int x = que.front(); que.pop();
            bo[x] = 0;
            for (int k = pre[x]; k != -1; k = edge[k].nex) {
                int y = edge[k].y;
                if (color[y] != color[x]) continue;
                static Bitset tmp;
                tmp = bit[y];
                bit[y] = bit[y] & bit[x];
                bit[y].set(y);
                if (!(tmp == bit[y]) && !bo[y]) {
                    bo[y] = 1;
                    que.push(y);
                }
            }
        }
        for (int j = 0; j < top[i].size(); ++j) {
            int x = top[i][j];
            for (int k = pre[x]; k != -1; k = edge[k].nex) {
                int y = edge[k].y;                 
                if (color[x] != color[y]) {
                    bit[y] = bit[y] & bit[x];
                    bit[y].set(y);
                }
            }
        }
    }
    for (int i = 0 ; i < Q ; ++ i) {
        int K = query[i].size();
        static Bitset tmp;
        tmp.Sset();
        for (int j = 0; j < K; ++ j) {
            int x = query[i][j];
            tmp = tmp & bit[x];
        }
        res[i] = min(res[i] , tmp.low() + 25000);
        printf("%d\n" , C[res[i]].first);
    }
    return 0;
}
accuracy: 1
time_ms: 410
memory_kb: 173928
final_rank: 5

code_snippet: #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cassert>
#include <cctype>
#include <stack>
#include <queue>
using namespace std;
typedef long long LL;
const int N = 50005;
const int M = 505;
typedef unsigned long long ULL;
 
int cnt, n;
 
struct Bitset {
    ULL a[M];
    Bitset () {
        memset(a , 0 , sizeof(a));
    }
    Bitset operator & (const Bitset &R) const {
        Bitset res = *this;
        for (int i = 0 ; i < M ; ++ i)
            res.a[i] &= R.a[i];
        return res;
    }
    void set(int x) {
        a[x >> 6] |= 1ULL << (x & 63);
    }
 
    void Sset() {
        for (int i = 0; i < M; ++i)
            a[i] |= ~0ULL;
    }
 
    int operator == (const Bitset &A) const {
        for (int i = 0; i < M; ++i)
            if (a[i] != A.a[i]) return 0;
        return 1;
    }
 
    int low() {
        for (int i = 0; i < M; ++i) {
            if (a[i] != 0) {
                for (int j = 0; j < 64; ++j)
                    if (a[i] >> j & 1) return (i << 6) | j;  
            }
        }
    }
 
    void  print() {
        for (int i = 0; i < n; ++i)
            printf("%llu ", a[i >> 6] >> (i & 63) & 1);
        puts("");
    }
} bit[N];
 
int  m , pre[N] , mcnt;
 
struct Edge {
    int y, nex;
}edge[N * 20];
 
int mark[N], dfn[N], color[N];
 
stack<int> sta;
vector<int> top[N];
bool u[N];
void dfs(int x) {
    static int sum = 0;
    mark[x] = dfn[x] = ++sum;
    sta.push(x); u[x] = 1;
    for (int k = pre[x]; k != -1; k = edge[k].nex){
        int y = edge[k].y;
        if (!dfn[y]) {
            dfs(y);
            mark[x] = min(mark[x], mark[y]);
        } else if (u[y]) {
            mark[x] = min(mark[x], dfn[y]);
        }
    }
    if (mark[x] == dfn[x]) {
        int y = -1;
        ++cnt;
        while (y != x) {
            y = sta.top();
            sta.pop();
            u[y] = 0;
            color[y] = cnt;
            mark[y] = 1 << 30;
            top[cnt].push_back(y);
            //   printf("!!%d %d\n", cnt, y);
        }
    }
}
 
pair<int, int> C[N];
int num[N];
int bo[N];
int m1[N * 10], m2[N * 10];
 
int main() {
 
    // cout << (sizeof(bit) >> 20) << endl;
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; ++i)
        scanf("%d%d", m1 + i, m2 + i);
    for (int i = 0; i < n; ++i) { 
        scanf("%d", &C[i].first);
        C[i].second = i;
    }
    sort(C, C + n);
    for (int i = 0; i < n; ++i) {
        num[C[i].second] = i;
    }
    memset(pre, -1, sizeof(pre));
    for (int i = 0 ; i < m ; ++ i) {
        int x = m1[i], y = m2[i];
        //scanf("%d%d", &x, &y);
        --x;
        --y;
        x = num[x];
        y = num[y];
        //printf("%d    %d\n", x, y);
        edge[mcnt] = (Edge) {y, pre[x]};
        pre[x] = mcnt++;
    }
    for (int i = 0; i < n; ++i)
        if (dfn[i] == 0) dfs(i);
    for (int i = 0; i < n; ++i) {
        if (i == num[0]) continue;
        bit[i].Sset();
    }
    bit[num[0]].set(num[0]);
    for (int i = cnt; i > 0; --i) {
        queue<int> que;
        for (int j = 0; j < top[i].size(); ++j) {
            que.push((top[i][j]));
            // cout << top[i][j] << " ";
        }
        //cout <<  "!!" << endl;
        while (!que.empty()) {
            int x = que.front(); que.pop();
            bo[x] = 0;
            for (int k = pre[x]; k != -1; k = edge[k].nex) {
                int y = edge[k].y;
                if (color[y] != color[x]) continue;
                static Bitset tmp;
                tmp = bit[y];
                bit[y] = bit[y] & bit[x];
                bit[y].set(y);
                if (!(tmp == bit[y]) && !bo[y]) {
                    bo[y] = 1;
                    que.push(y);
                }
            }
        }
        for (int j = 0; j < top[i].size(); ++j) {
            int x = top[i][j];
            //  cout << x << " ";
            //bit[x].print();
            for (int k = pre[x]; k != -1; k = edge[k].nex) {
                int y = edge[k].y;
                 
                if (color[x] != color[y]) {
                    //      printf("%d -> %d\n", x, y);
                    bit[y] = bit[y] & bit[x];
                    bit[y].set(y);
                }
            }
        }
    }
    //for (int i = 0; i < n; ++i) {
    //    printf("%d %d\n", i, num[i]);
    //    bit[i].print();
         
    //}
    int Q;
    scanf("%d", &Q);
    while (Q--) {
        int K;
        scanf("%d", &K);
        static Bitset tmp;
        tmp.Sset();
        for (int i = 0; i < K; ++i) {
            int x;
            scanf("%d", &x);
            tmp = tmp & bit[num[x - 1]];
        }
        int t = tmp.low();
        printf("%d\n", C[t].first);
    }
    return 0;
}
accuracy: 0.23214285714285715
time_ms: 220
memory_kb: 207644
final_rank: 17

code_snippet: #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cassert>
#include <cctype>
#include <stack>
#include <queue>
using namespace std;
typedef long long LL;
const int N = 40005;
const int M = 626;
typedef unsigned long long ULL;

int cnt, n;

struct Bitset {
    ULL a[M];
    Bitset () {
        memset(a , 0 , sizeof(a));
    }
    Bitset operator & (const Bitset &R) const {
        Bitset res = *this;
        for (int i = 0 ; i < M ; ++ i)
            res.a[i] &= R.a[i];
        return res;
    }
    void set(int x) {
        a[x >> 6] |= 1LL << (x & 63);
    }

    void Sset() {
        for (int i = 0; i < M; ++i)
            a[i] |= ~0ULL;
    }

    int operator == (const Bitset &A) const {
        for (int i = 0; i < M; ++i)
            if (a[i] != A.a[i]) return 0;
        return 1;
    }

    int low() {
        for (int i = 0; i < M; ++i) {
            if (a[i] != 0) {
                for (int j = 0; j < 64; ++j)
                    if (a[i] >> j & 1) return (i << 6) | j;  
            }
        }
    }

    void  print() {
        for (int i = 0; i < n; ++i)
            printf("%llu ", a[i >> 6] >> (i & 63) & 1);
        puts("");
    }
} bit[N];

int  m , pre[N] , mcnt;

struct Edge {
    int y, nex;
}edge[N * 20];

int mark[N], dfn[N], color[N];

stack<int> sta;
vector<int> top[N];
bool u[N];
void dfs(int x) {
    static int sum = 0;
    mark[x] = dfn[x] = ++sum;
    sta.push(x); u[x] = 1;
    for (int k = pre[x]; k != -1; k = edge[k].nex){
        int y = edge[k].y;
        if (!dfn[y]) {
            dfs(y);
            mark[x] = min(mark[x], mark[y]);
        } else if (u[y]) {
            mark[x] = min(mark[x], dfn[y]);
        }
    }
    if (mark[x] == dfn[x]) {
        int y = -1;
        ++cnt;
        while (y != x) {
            y = sta.top();
            sta.pop();
            u[y] = 0;
            color[y] = cnt;
            mark[y] = 1 << 30;
            top[cnt].push_back(y);
            //   printf("!!%d %d\n", cnt, y);
        }
    }
}

pair<int, int> C[N];
int num[N];
int bo[N];
int m1[N * 10], m2[N * 10];

int main() {

    // cout << (sizeof(bit) >> 20) << endl;
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; ++i)
        scanf("%d%d", m1 + i, m2 + i);
    for (int i = 0; i < n; ++i) { 
        scanf("%d", &C[i].first);
        C[i].second = i;
    }
    sort(C, C + n);
    for (int i = 0; i < n; ++i) {
        num[C[i].second] = i;
    }
    memset(pre, -1, sizeof(pre));
    for (int i = 0 ; i < m ; ++ i) {
        int x = m1[i], y = m2[i];
        //scanf("%d%d", &x, &y);
        --x;
        --y;
        x = num[x];
        y = num[y];
        //printf("%d    %d\n", x, y);
        edge[mcnt] = (Edge) {y, pre[x]};
        pre[x] = mcnt++;
    }
    for (int i = 0; i < n; ++i)
        if (dfn[i] == 0) dfs(i);
    for (int i = 0; i < n; ++i) {
        if (i == num[0]) continue;
        bit[i].Sset();
    }
    bit[num[0]].set(num[0]);
    for (int i = cnt; i > 0; --i) {
        queue<int> que;
        for (int j = 0; j < top[i].size(); ++j) {
            que.push((top[i][j]));
            // cout << top[i][j] << " ";
        }
        //cout <<  "!!" << endl;
        while (!que.empty()) {
            int x = que.front(); que.pop();
            bo[x] = 0;
            for (int k = pre[x]; k != -1; k = edge[k].nex) {
                int y = edge[k].y;
                if (color[y] != color[x]) continue;
                static Bitset tmp;
                tmp = bit[y];
                bit[y] = bit[y] & bit[x];
                bit[y].set(y);
                if (!(tmp == bit[y]) && !bo[y]) {
                    bo[y] = 1;
                    que.push(y);
                }
            }
        }
        for (int j = 0; j < top[i].size(); ++j) {
            int x = top[i][j];
            //  cout << x << " ";
            //bit[x].print();
            for (int k = pre[x]; k != -1; k = edge[k].nex) {
                int y = edge[k].y;
                
                if (color[x] != color[y]) {
                    //      printf("%d -> %d\n", x, y);
                    bit[y] = bit[y] & bit[x];
                    bit[y].set(y);
                }
            }
        }
    }
    //for (int i = 0; i < n; ++i) {
    //    printf("%d %d\n", i, num[i]);
    //    bit[i].print();
        
    //}
    int Q;
    scanf("%d", &Q);
    while (Q--) {
        int K;
        scanf("%d", &K);
        static Bitset tmp;
        tmp.Sset();
        for (int i = 0; i < K; ++i) {
            int x;
            scanf("%d", &x);
            tmp = tmp & bit[num[x - 1]];
        }
        int t = tmp.low();
        printf("%d\n", C[t].first);
    }
    return 0;
}
accuracy: 0.23214285714285715
time_ms: 130
memory_kb: 202788
final_rank: 16

code_snippet: #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cassert>
#include <cctype>
#include <stack>
#include <queue>
using namespace std;
typedef long long LL;
const int N = 25005;
const int M = 400;
typedef unsigned long long ULL;

int cnt, n;

struct Bitset {
    ULL a[M];
    Bitset () {
        memset(a , 0 , sizeof(a));
    }
    Bitset operator & (const Bitset &R) const {
        Bitset res = *this;
        for (int i = 0 ; i < M ; ++ i)
            res.a[i] &= R.a[i];
        return res;
    }
    void set(int x) {
        a[x >> 6] |= 1LL << (x & 63);
    }

    void Sset() {
        for (int i = 0; i < M; ++i)
            a[i] |= ~0ULL;
    }

    int operator == (const Bitset &A) const {
        for (int i = 0; i < M; ++i)
            if (a[i] != A.a[i]) return 0;
        return 1;
    }

    int low() {
        for (int i = 0; i < M; ++i) {
            if (a[i] != 0) {
                for (int j = 0; j < 64; ++j)
                    if (a[i] >> j & 1) return (i << 6) | j;  
            }
        }
    }

    void  print() {
        for (int i = 0; i < n; ++i)
            printf("%llu ", a[i >> 6] >> (i & 63) & 1);
        puts("");
    }
} bit[N];

int  m , pre[N] , mcnt;

struct Edge {
    int y, nex;
}edge[N * 20];

int mark[N], dfn[N], color[N];

stack<int> sta;
vector<int> top[N];
bool u[N];
void dfs(int x) {
    static int sum = 0;
    mark[x] = dfn[x] = ++sum;
    sta.push(x); u[x] = 1;
    for (int k = pre[x]; k != -1; k = edge[k].nex){
        int y = edge[k].y;
        if (!dfn[y]) {
            dfs(y);
            mark[x] = min(mark[x], mark[y]);
        } else if (u[y]) {
            mark[x] = min(mark[x], dfn[y]);
        }
    }
    if (mark[x] == dfn[x]) {
        int y = -1;
        ++cnt;
        while (y != x) {
            y = sta.top();
            sta.pop();
            u[y] = 0;
            color[y] = cnt;
            mark[y] = 1 << 30;
            top[cnt].push_back(y);
            //   printf("!!%d %d\n", cnt, y);
        }
    }
}

pair<int, int> C[N];
int num[N];
int bo[N];
int m1[N * 10], m2[N * 10];

int main() {

    // cout << (sizeof(bit) >> 20) << endl;
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; ++i)
        scanf("%d%d", m1 + i, m2 + i);
    for (int i = 0; i < n; ++i) { 
        scanf("%d", &C[i].first);
        C[i].second = i;
    }
    sort(C, C + n);
    for (int i = 0; i < n; ++i) {
        num[C[i].second] = i;
    }
    memset(pre, -1, sizeof(pre));
    for (int i = 0 ; i < m ; ++ i) {
        int x = m1[i], y = m2[i];
        //scanf("%d%d", &x, &y);
        --x;
        --y;
        x = num[x];
        y = num[y];
        //printf("%d    %d\n", x, y);
        edge[mcnt] = (Edge) {y, pre[x]};
        pre[x] = mcnt++;
    }
    for (int i = 0; i < n; ++i)
        if (dfn[i] == 0) dfs(i);
    for (int i = 0; i < n; ++i) {
        if (i == num[0]) continue;
        bit[i].Sset();
    }
    bit[num[0]].set(num[0]);
    for (int i = cnt; i > 0; --i) {
        queue<int> que;
        for (int j = 0; j < top[i].size(); ++j) {
            que.push((top[i][j]));
            // cout << top[i][j] << " ";
        }
        //cout <<  "!!" << endl;
        while (!que.empty()) {
            int x = que.front(); que.pop();
            bo[x] = 0;
            for (int k = pre[x]; k != -1; k = edge[k].nex) {
                int y = edge[k].y;
                if (color[y] != color[x]) continue;
                static Bitset tmp;
                tmp = bit[y];
                bit[y] = bit[y] & bit[x];
                bit[y].set(y);
                if (!(tmp == bit[y]) && !bo[y]) {
                    bo[y] = 1;
                    que.push(y);
                }
            }
        }
        for (int j = 0; j < top[i].size(); ++j) {
            int x = top[i][j];
            //  cout << x << " ";
            //bit[x].print();
            for (int k = pre[x]; k != -1; k = edge[k].nex) {
                int y = edge[k].y;
                
                if (color[x] != color[y]) {
                    //      printf("%d -> %d\n", x, y);
                    bit[y] = bit[y] & bit[x];
                    bit[y].set(y);
                }
            }
        }
    }
    //for (int i = 0; i < n; ++i) {
    //    printf("%d %d\n", i, num[i]);
    //    bit[i].print();
        
    //}
    int Q;
    scanf("%d", &Q);
    while (Q--) {
        int K;
        scanf("%d", &K);
        static Bitset tmp;
        tmp.Sset();
        for (int i = 0; i < K; ++i) {
            int x;
            scanf("%d", &x);
            tmp = tmp & bit[num[x - 1]];
        }
        int t = tmp.low();
        printf("%d\n", C[t].first);
    }
    return 0;
}
accuracy: 0.23214285714285715
time_ms: 60
memory_kb: 82968
final_rank: 15