题目大意:
一个无向图 Q个询问 每次给一些点的集合
求有多少个点满足去掉这个点后使这些点的集合中有一个点对不连通
思路:
点双缩点 相当于每次求这些点中的所有路径上的圆点个数
可以将这些点按dfs序排序 每次求a i 和 a i+1两个点路径上的圆点个数
最后答案/2 后减去这些点的个数(因为不能取这些点) 再判断 a i 和a n的lca是否是圆点
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 400100 12 #define V1 (g1.to[i]) 13 #define V2 (g2.to[i]) 14 using namespace std; 15 inline int read() 16 { 17 int x=0,f=1;char ch=getchar(); 18 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 19 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 20 return x*f; 21 } 22 int n,m; 23 int dfn[MAXN],st[MAXN],low[MAXN],top,stp; 24 int f[MAXN][18],dep[MAXN],dis[MAXN]; 25 struct graph 26 { 27 int fst[MAXN],nxt[MAXN<<2],to[MAXN<<2],cnt; 28 void mem(){memset(fst,0,sizeof(fst));cnt=0;} 29 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;} 30 }g1,g2; 31 void tarjan(int x) 32 { 33 dfn[x]=low[x]=++stp,st[++top]=x;int now=0; 34 for(int i=g1.fst[x];i;i=g1.nxt[i]) 35 if(!dfn[V1]) 36 { 37 tarjan(V1);low[x]=min(low[x],low[V1]); 38 if(low[V1]<dfn[x]) continue;m++; 39 do{now=st[top--];g2.add(m,now);} 40 while(now!=V1);g2.add(x,m); 41 } 42 else low[x]=min(low[x],dfn[V1]); 43 } 44 void dfs(int x) 45 { 46 dfn[x]=++stp; 47 for(int i=1;(1<<i)<=dep[x];i++) f[x][i]=f[f[x][i-1]][i-1]; 48 for(int i=g2.fst[x];i;i=g2.nxt[i]) 49 {f[V2][0]=x,dep[V2]=dep[x]+1,dis[V2]=dis[x]+(V2<=n);dfs(V2);} 50 } 51 int lca(int a,int b) 52 { 53 if(dep[a]<dep[b]) swap(a,b); 54 int t=dep[a]-dep[b]; 55 for(int i=17;i>=0;i--) if((1<<i)&t) a=f[a][i]; 56 if(a==b) return a; 57 for(int i=17;i>=0;i--) if(f[a][i]!=f[b][i]) a=f[a][i],b=f[b][i]; 58 return f[a][0]; 59 } 60 bool cmp(const int &a,const int &b) {return dfn[a]<dfn[b];} 61 inline int calc(int a,int b) {return dis[a]+dis[b]-(dis[lca(a,b)]<<1);} 62 int main() 63 { 64 int T=read(),a,b,k,q,res; 65 while(T--) 66 { 67 g1.mem();g2.mem();memset(dfn,0,sizeof(dfn)); 68 memset(f,0,sizeof(f)); 69 n=read(),m=read(),stp=top=0; 70 while(m--) {a=read(),b=read();g1.add(a,b);g1.add(b,a);} 71 m=n;tarjan(1);dis[1]=dep[1]=1,stp=0;dfs(1); 72 q=read(); 73 while(q--) 74 { 75 k=read(),top=0,res=0; 76 while(k--) st[++top]=read(); 77 sort(st+1,st+top+1,cmp); 78 for(int i=1;i<=top;i++) 79 res+=calc(st[i],st[i%top+1]); 80 if(lca(st[1],st[top])<=n) printf("%d ",(res+2-top*2)>>1); 81 else printf("%d ",(res-top*2)>>1); 82 } 83 } 84 }