HDU 2460 Network(桥+LCA)

http://acm.hdu.edu.cn/showproblem.php?pid=2460

题意:
给出图,求每次增加一条边后图中桥的数量。

 

思路:

先用tarjan算法找出图中所有的桥,如果lowv>pre[u],那么u—v就是桥,此时可以标记一下v。

之后就是利用LCA,找到两个节点的公共祖先,在这条路径上的桥就不再是桥了。(此时就相当于这些桥组成的树,可以在脑海中缩点)

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<sstream>
  6 #include<vector>
  7 #include<stack>
  8 #include<queue>
  9 #include<cmath>
 10 #include<map>
 11 #include<set>
 12 using namespace std;
 13 typedef long long ll;
 14 typedef pair<int,int> pll;
 15 const int INF = 0x3f3f3f3f;
 16 const int maxn=100000+5;
 17 
 18 int n, m;
 19 int tot;
 20 int cnt;
 21 int head[maxn];
 22 int dfs_clock;
 23 int pre[maxn];
 24 int low[maxn];
 25 int isbridge[maxn];
 26 int p[maxn];
 27 
 28 struct node
 29 {
 30     int v;
 31     int next;
 32 }e[400000+5];
 33 
 34 void addEdge(int u, int v)
 35 {
 36     e[tot].v=v;
 37     e[tot].next=head[u];
 38     head[u]=tot++;
 39 }
 40 
 41 void init()
 42 {
 43     cnt=0;
 44     dfs_clock=0;
 45     memset(pre,0,sizeof(pre));
 46     memset(isbridge,0,sizeof(isbridge));
 47     for(int i=1;i<=n;i++)  p[i]=i;
 48 }
 49 
 50 int dfs(int u, int fa)
 51 {
 52     int lowu=pre[u]=++dfs_clock;
 53     for(int i=head[u];i!=-1;i=e[i].next)
 54     {
 55         int v=e[i].v;
 56         if(!pre[v])
 57         {
 58             p[v]=u;
 59             int lowv=dfs(v,u);
 60             lowu=min(lowu,lowv);
 61             if(lowv>pre[u])   {cnt++;isbridge[v]=1;}
 62         }
 63         else if(pre[v]<pre[u] && v!=fa)
 64             lowu=min(lowu,pre[v]);
 65     }
 66     return low[u]=lowu;
 67 }
 68 
 69 int LCA(int u, int v)
 70 {
 71     while(low[u]>low[v])
 72     {
 73         if(isbridge[u])  {cnt--;isbridge[u]=0;}
 74         u=p[u];
 75     }
 76     while(low[v]>low[u])
 77     {
 78         if(isbridge[v])  {cnt--;isbridge[v]=0;}
 79         v=p[v];
 80     }
 81     while(u!=v)
 82     {
 83         if(isbridge[u])  {cnt--;isbridge[u]=0;}
 84         if(isbridge[v])  {cnt--;isbridge[v]=0;}
 85         u=p[u];
 86         v=p[v];
 87     }
 88 }
 89 
 90 int main()
 91 {
 92     //freopen("in.txt","r",stdin);
 93     int kase=0;
 94     while(~scanf("%d%d",&n,&m))
 95     {
 96         if(n==0 && m==0)  break;
 97         tot=0;
 98         memset(head,-1,sizeof(head));
 99         while(m--)
100         {
101             int u,v;
102             scanf("%d%d",&u,&v);
103             addEdge(u,v);
104             addEdge(v,u);
105         }
106         init();
107         dfs(1,-1);
108         int q;
109         scanf("%d",&q);
110         printf("Case %d:\n",++kase);
111         while(q--)
112         {
113             int u,v;
114             scanf("%d%d",&u,&v);
115             LCA(u,v);
116             printf("%d\n",cnt);
117         }
118         printf("\n");
119     }
120     return 0;
121 }

 

posted @ 2017-08-07 08:00  Kayden_Cheung  阅读(246)  评论(0编辑  收藏  举报
//目录