发现在图上并不好做,又和tarjan有关,所以搞个圆方树出来
然后就可以dp了
询问有点多,但是发现
∑
∣
s
∣
≤
2
∗
1
0
5
\sum{|s|}\leq2*10^5
∑∣s∣≤2∗105,想到了什么(看标题)
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
int n,m;
const int N=2e5+5;
struct E{
int vis[N<<1],head[N<<1],nxt[N<<1],tot=0;
inline void add(int x,int y){
if(x==y) return;
vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;
vis[++tot]=x;nxt[tot]=head[y];head[y]=tot;
}
inline void clear(){tot=0;memset(head,0,sizeof(head));}
}tar,tr,ntr;
int cnt=1;
int dfn[N],low[N],sign=0,sta[N],dcc;
void tarjan(int v){
dfn[v]=low[v]=++sign;sta[++sta[0]]=v;
for(int i=tar.head[v];i;i=tar.nxt[i]){
int y=tar.vis[i];
if(!dfn[y]){
tarjan(y);low[v]=min(low[v],low[y]);
if(low[y]>=dfn[v]){
tr.add(++cnt,v);int x=0;
do{x=sta[sta[0]--];tr.add(cnt,x);}while(x!=y);
}
}
else low[v]=min(low[v],dfn[y]);
}
}
int dis[N],fa[N],pt[N],dep[N],hson[N],siz[N],cur=0,gra[N][19];
void dfs(int u, int fa){
dis[u]=0,dep[u]=0;
gra[u][0]=fa,dfn[u]=++cur,dep[u]=dep[fa]+1;
if(u<=n) dis[u]+=1;dis[u]+=dis[fa];
for(int i=1;i<19;i++) gra[u][i]=gra[gra[u][i-1]][i-1];
for(int i=tr.head[u];i;i=tr.nxt[i]){
int v=tr.vis[i];
if(v!=fa) dfs(v,u);
}
}
inline int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=18;~i;i--)
if(dep[gra[x][i]]>=dep[y]) x=gra[x][i];
for(int i=18;~i;i--)
if(gra[x][i]!=gra[y][i])
x=gra[x][i],y=gra[y][i];
return x==y?x:gra[x][0];
}
int ans=0;
inline bool cmp(int a,int b){return dfn[a]<dfn[b];}
void dp(int v,int fa){
for(int i=ntr.head[v];i;i=ntr.nxt[i]){
int y=ntr.vis[i];
if(y==fa) continue;
dp(y,v);ans+=dis[y]-dis[v];
}
ntr.head[v]=0;
}
int a[N];
inline void build(){
ntr.tot=0;
int k=read();cnt=1,sta[1]=1,sta[0]=1;
for(int i=1;i<=k;i++) a[i]=read();
sort(a+1,a+k+1,cmp);
int l=a[1];
for(int i=1;i<=k;i++){
int lc=lca(sta[sta[0]],a[i]);
l=lca(l,a[i]);
while(1){
if(dep[lc]>=dep[sta[sta[0]-1]]){
ntr.add(sta[sta[0]],lc);sta[0]--;
if(lc!=sta[sta[0]]) sta[++sta[0]]=lc;
break;
}
if(sta[0]) ntr.add(sta[sta[0]],sta[sta[0]-1]),sta[0]--;
}
sta[++sta[0]]=a[i];
}
while(sta[0]>1) ntr.add(sta[sta[0]],sta[sta[0]-1]),sta[0]--;
ans=0,dp(1,0);
if(l>n) cout<<ans-dis[l]+1-k<<"\n";
else cout<<ans-dis[l]+2-k<<"\n";
}
inline void init(){tar.clear();tr.clear();sign=0;cur=0;memset(pt,0,sizeof(pt));}
int main(){
int t=read();
while(t--){
init();
n=cnt=read();m=read();
for(int i=1;i<=n;i++) dfn[i]=low[i]=0;
for(int x,y,i=1;i<=m;i++){
x=read(),y=read();
tar.add(x,y);
}
sta[0]=0;tarjan(1);
int q=read();
dfs(1,0);
for(int i=1;i<=q;i++) build();
}
return 0;
}