蒟蒻boom 0 在线求助
查看原帖
蒟蒻boom 0 在线求助
234224
青鸟_Blue_Bird楼主2020/6/5 23:19
#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define isdigit(c) ((c)>='0'&&(c)<='9')
#define v1 a1.t[i].v
#define v2 a2.t[i].v

int read(){
	int x = 0, s = 1;
	char c = getchar();
	while(!isdigit(c)){
		if(c == '-')s = -1;
		c = getchar();
	} 
	while(isdigit(c)){
		x = (x << 1) + (x << 3) + (c ^ '0');
		c = getchar();
	}
	return x * s;
}

struct tu{
	int u, v;
	int next;
};
int a[N];

struct node{
	tu t[N << 1];
	int f[N << 1];
	
	int bian;
	inline void add(int u, int v){
		t[++bian] = (tu){u, v, f[u]}, f[u] = bian;
		t[++bian] = (tu){v, u, f[v]}, f[v] = bian;
		return ;
	}
	
	inline void clean(){
		memset(f, 0, sizeof(f));
		for(int i = 1;i <= (N << 1); i++)
			t[i] = (tu){0, 0, 0};
		bian = 0;
		return ;
	}
	
} a1, a2;

int dfn[N], low[N], cac = 0;
int stac[N], top = 0, cnt = 0;
int n, m;
void tarjan(int now){
	low[now] = dfn[now] = ++cac;
	stac[++top] = now;
	for(int i = a1.f[now]; i; i = a1.t[i].next){
		if(!dfn[v1]){
			tarjan(v1);
			low[now] = min(low[now], low[v1]);
			if(low[v1] == dfn[now]){
				++cnt;
				for(int x = 0; x != v1; --top){
					x = stac[top];
					a2.add(cnt, x);
				}
				a2.add(now, cnt);
			}
		} 
		else 
			low[now] = min(low[now], dfn[v1]);
	}
	return ;
}

namespace LCA{
	int son[N], top[N], fa[N], siz[N], deth[N];	
	int dfn[N], id = 0;
	void dfs1(int now, int father){
		fa[now] = father;
		deth[now] = deth[father] + 1;
		siz[now] = 1;
		int maxn = -1;
		for(int i = a2.f[now]; i; i = a2.t[i].next){
			if(v2 != father){
				dfs1(v2, now);
				siz[now] += siz[v2];
				if(siz[v2] >= maxn){
					maxn = siz[v2];
					son[now] = v2;
				}
			}
		}	
		return ;
	}

	
	void dfs2(int now, int tp){
		dfn[now] = ++id; 
		top[now] = tp;
		if(!son[now]) return ;
		dfs2(son[now], tp);
		for(int i = a2.f[now]; i; i = a2.t[i].next){
			if(v2 != fa[now] && v2 != son[now])
				dfs2(v2, v2);
		}
		return ;
	}
	
	int get_lca(int x, int y){
		while(top[x] != top[y]){
			if(deth[top[y]] >= deth[top[x]]){
				y = fa[top[y]]; /*一定要跳到链首的父亲节点,不然还在同一条链上*/
			}
			else x = fa[top[x]];
		}
		return deth[x] <= deth[y] ? x : y; /*lca肯定是深度比较小(在上面的)的那个*/
	} 
	
	void clean(){
		id = 0;
		memset(son, 0, sizeof(son));
		deth[1] = 0;
		return ;
	}
	
}

int tern[N], id = 0;
int dis[N];
void dfs(int now, int father){
	tern[now] = ++id;
	dis[now] = dis[father] + (now <= n);
	for(int i = a2.f[now]; i; i = a2.t[i].next){
		if(v2 != father)
			dfs(v2, now);
	}
	return ;
} 
bool cmp(int x, int y){
	return tern[x] < tern[y];
}

int main(){
	freopen("hh.txt", "r", stdin);
	int T = read();
	while(T--){
		n = read(), m = read();
		a1.clean(), a2.clean();
		memset(dfn, 0, sizeof(dfn));
		memset(low, 0, sizeof(low));
		LCA::clean();
		for(int i = 1;i <= m; i++){
			int x = read(), y = read();
			a1.add(x, y);
		}
		cnt = n;
		cac = 0;
		tarjan(1), --top;
		LCA::dfs1(1, 1);
		LCA::dfs2(1, 1);
		dfs(1, 1);
		int q = read();
		while(q--){
			int s = read();
			int ans = -2 * s;
			for(int i = 1;i <= s; i++)a[i] = read();
			sort(a + 1, a + s + 1, cmp);
			for(int i = 1;i <= s; i++){
				int u = a[i], v = a[i % s + 1];
				ans += dis[u] + dis[v] - 2 * dis[LCA::get_lca(u, v)];
			}
			if(LCA::get_lca(a[1], a[s]) <= n) ans += 2;
			printf("%d\n", ans / 2);
		}
	}
	return 0;
}
2020/6/5 23:19
加载中...