bzoj 5329 战略游戏

题目大意:

一个无向图 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\n",(res+2-top*2)>>1);
81             else printf("%d\n",(res-top*2)>>1);
82         }
83     }
84 }
View Code

 

posted @ 2018-10-10 20:46  jack_yyc  阅读(133)  评论(0编辑  收藏  举报