有一个圆方树,每次给出一个点集,询问虚树上圆点数量-询问点数量
sol:题意读懂就很简单了...可以建虚树dp
也可以考虑每一条链对答案的贡献,最后要注意单独计算虚树根对答案的贡献
#pragma GCC optimize("-funsafe-loop-optimizations") #pragma GCC optimize("-funroll-loops") #pragma GCC optimize("-fwhole-program") #pragma GCC optimize("Ofast,no-stack-protector") #pragma GCC optimize("-fthread-jumps") #pragma GCC optimize("-falign-functions") #pragma GCC optimize("-falign-jumps") #pragma GCC optimize("-falign-loops") #pragma GCC optimize("-falign-labels") #pragma GCC optimize("-fcaller-saves") #pragma GCC optimize("-fcrossjumping") #pragma GCC optimize("-fcse-follow-jumps") #pragma GCC optimize("-fcse-skip-blocks") #pragma GCC optimize("-fdelete-null-pointer-checks") #pragma GCC optimize("-fdevirtualize") #pragma GCC optimize("-fexpensive-optimizations") #pragma GCC optimize("-fgcse") #pragma GCC optimize("-fgcse-lm") #pragma GCC optimize("-fhoist-adjacent-loads") #pragma GCC optimize("-finline-small-functions") #pragma GCC optimize("-findirect-inlining") #pragma GCC optimize("-fipa-sra") #pragma GCC optimize("-foptimize-sibling-calls") #pragma GCC optimize("-fpartial-inlining") #pragma GCC optimize("-fpeephole2") #pragma GCC optimize("-freorder-blocks") #pragma GCC optimize("-freorder-functions") #pragma GCC optimize("-frerun-cse-after-loop") #pragma GCC optimize("-fsched-interblock") #pragma GCC optimize("-fsched-spec") #pragma GCC optimize("-fschedule-insns") #pragma GCC optimize("-fschedule-insns2") #pragma GCC optimize("-fstrict-aliasing") #pragma GCC optimize("-fstrict-overflow") #pragma GCC optimize("-ftree-switch-conversion") #pragma GCC optimize("-ftree-tail-merge") #pragma GCC optimize("-ftree-pre") #pragma GCC optimize("-ftree-vrp") #pragma GCC target("avx") #include<bits/stdc++.h> #define LL long long using namespace std; #define gtchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++) static char buf[1000000],*p1=buf,*p2=buf; inline int read() { int x = 0,f = 1;char ch = gtchar(); for(;!isdigit(ch);ch = gtchar())if(ch == '-')f = -f; for(;isdigit(ch);ch = gtchar())x = 10 * x + ch - '0'; return x * f; } int n,m; const int maxn = 2e5 + 10; vector<int> G[maxn],Tree[maxn]; int dfn[maxn],low[maxn],_tim,stk[maxn],top,vis[maxn]; int tot; inline void write(int x,char opt = 0) { int t=10,len=1; while(t<=x)t*=10,len++; while(len--)t/=10,putchar(x/t+48),x%=t; if(opt)putchar(opt); return; } inline void Tarjan(int x,int fa) { dfn[x] = low[x] = ++_tim;stk[++top] = x;vis[x] = 1; for(auto targ : G[x]) { if(targ == fa)continue; if(!vis[targ]) { Tarjan(targ,x); low[x] = min(low[x],low[targ]); if(low[targ] >= dfn[x]) { tot++; Tree[x].push_back(tot); do { Tree[tot].push_back(stk[top]); }while(targ != stk[top--]); } } else low[x] = min(low[x],dfn[targ]); } } int s[maxn]; int fa[maxn],dep[maxn],size[maxn],bl[maxn],dis[maxn]; inline void dfs1(int x) { size[x] = 1; for(auto targ : Tree[x]) { if(targ == fa[x])continue; fa[targ] = x; dis[targ] = dis[x] + (targ <= n); dep[targ] = dep[x] + 1; dfs1(targ); size[x] += size[targ]; } } inline void dfs2(int x,int col) { int k = 0; bl[x] = col;dfn[x] = ++_tim; for(auto targ : Tree[x]) if(dep[targ] > dep[x] && size[targ] > size[k])k = targ; if(!k){low[x] = _tim;return;} dfs2(k,col); for(auto targ : Tree[x]) if(dep[targ] > dep[x] && targ != k)dfs2(targ,targ); low[x] = _tim; } inline int lca(int x,int y) { while(bl[x] != bl[y]) { if(dep[bl[x]] < dep[bl[y]])swap(x,y); x = fa[bl[x]]; } return dep[x] < dep[y] ? x : y; } int q[maxn]; int main() { int T = read(); while(T--) { _tim = 0; tot = n = read();m = read(); for(int i=1;i<maxn;i++)G[i].clear(),Tree[i].clear(); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(vis,0,sizeof(vis)); for(int i=1;i<=m;i++) { int u = read(),v = read(); G[u].push_back(v);G[v].push_back(u); } for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i,0); int ques = read();_tim = 0;dis[1] = 1;dfs1(1),dfs2(1,1); while(ques--) { int len = read();int k = len,top = 0,ans = 0; for(int i=1;i<=len;i++)s[i] = read(); sort(s + 1,s + len + 1,[](int u,int v){return dfn[u] < dfn[v];}); for(int i=1;i<k;i++)s[++len] = lca(s[i],s[i + 1]); sort(s + 1,s + len + 1,[](int u,int v){return dfn[u] < dfn[v];}); len = unique(s + 1,s + len + 1) - (s + 1); if(s[1] <= n)ans = 1; else ans = 0; for(int i=1;i<=len;i++) { while(top && low[q[top]] < dfn[s[i]])top--; if(top)ans += (dis[s[i]] - dis[q[top]]); q[++top] = s[i]; } write(ans - k,' '); } } }