先圆方树然后建虚树,答案就是虚树大小。虚树没必要建出来,把原来的点的点权设为1,直接dfs序排序后相邻点求距离加上首尾两个点的距离,最后除以二(画一下可以发现是正反算了两遍),注意还要去掉询问点和补上首尾两个点的LCA
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<algorithm> 5 #define vint vector<int> 6 #define vit vector<int> ::iterator 7 using namespace std; 8 const int N=200005,M=800005; 9 int T,n,m,c,q,o,t1,t2,rt,pt,cnt,Cnt,tot; 10 int dfn[N],low[N],stk[N],isc[N],col[N]; 11 int p[N],noww[M],goal[M],P[N],Noww[M],Goal[M]; 12 int siz[N],dep[N],fth[N],imp[N],top[N],qry[M],dis[N]; vint pbc[N]; 13 void Link(int f,int t) 14 { 15 noww[++cnt]=p[f]; 16 goal[cnt]=t,p[f]=cnt; 17 noww[++cnt]=p[t]; 18 goal[cnt]=f,p[t]=cnt; 19 } 20 void Linka(int f,int t) 21 { 22 Noww[++Cnt]=P[f]; 23 Goal[Cnt]=t,P[f]=Cnt; 24 Noww[++Cnt]=P[t]; 25 Goal[Cnt]=f,P[t]=Cnt; 26 } 27 bool cmp(int a,int b) 28 { 29 return dfn[a]<dfn[b]; 30 } 31 void Init() 32 { 33 memset(p,0,sizeof p); 34 memset(P,0,sizeof P); 35 memset(dfn,0,sizeof dfn); 36 memset(low,0,sizeof low); 37 memset(imp,0,sizeof imp); 38 memset(top,0,sizeof top); 39 for(int i=1;i<=c;i++) pbc[i].clear(); 40 cnt=Cnt=tot=c=0; 41 } 42 void RTPBC(int nde) 43 { 44 int tmp=0; 45 dfn[nde]=low[nde]=++tot,stk[++pt]=nde; 46 for(int i=p[nde],g;i;i=noww[i]) 47 if(!dfn[g=goal[i]]) 48 { 49 RTPBC(g),low[nde]=min(low[nde],low[g]); 50 if(dfn[nde]<=low[g]) 51 { 52 if(nde!=rt||++tmp>1) isc[nde]=true; 53 int tep; c++; 54 do 55 { 56 tep=stk[pt--],col[tep]=c; 57 pbc[c].push_back(tep); 58 }while(tep!=g); 59 pbc[c].push_back(nde); 60 } 61 } 62 else low[nde]=min(low[nde],dfn[g]); 63 } 64 void DFS(int nde,int far,int dth) 65 { 66 int tmp=0; 67 siz[nde]=1,fth[nde]=far,dep[nde]=dth; 68 for(int i=P[nde],g;i;i=Noww[i]) 69 if((g=Goal[i])!=far) 70 { 71 dis[g]=dis[nde]+(g<=n); 72 DFS(g,nde,dth+1),siz[nde]+=siz[g]; 73 if(siz[g]>tmp) tmp=siz[g],imp[nde]=g; 74 } 75 } 76 void Mark(int nde,int upt) 77 { 78 top[nde]=upt,dfn[nde]=++tot; 79 if(imp[nde]) 80 { 81 Mark(imp[nde],upt); 82 for(int i=P[nde],g;i;i=Noww[i]) 83 if((g=Goal[i])!=fth[nde]&&g!=imp[nde]) Mark(g,g); 84 } 85 } 86 int LCA(int x,int y) 87 { 88 while(top[x]!=top[y]) 89 { 90 if(dep[top[x]]<dep[top[y]]) 91 swap(x,y); x=fth[top[x]]; 92 } 93 return dep[x]<dep[y]?x:y; 94 } 95 int Dist(int x,int y) 96 { 97 int lca=LCA(x,y); 98 return dis[x]+dis[y]-2*dis[lca]; 99 } 100 int main() 101 { 102 scanf("%d",&T); 103 while(T--) 104 { 105 Init(); 106 scanf("%d%d",&n,&m); 107 for(int i=1;i<=m;i++) 108 scanf("%d%d",&t1,&t2),Link(t1,t2); 109 RTPBC(rt=1); 110 for(int i=1;i<=c;i++) 111 for(vit it=pbc[i].begin();it!=pbc[i].end();it++) Linka(*it,n+i); 112 tot=0,DFS(1,0,1),Mark(1,1); 113 scanf("%d",&q); 114 while(q--) 115 { 116 scanf("%d",&o); int ans=0; 117 for(int i=1;i<=o;i++) scanf("%d",&qry[i]); 118 sort(qry+1,qry+1+o,cmp),qry[++o]=qry[1]; 119 for(int i=2;i<=o;i++) ans+=Dist(qry[i],qry[i-1]); 120 printf("%d ",(ans>>1)-o+1+(LCA(qry[o],qry[o-1])<=n)); 121 } 122 } 123 return 0; 124 }