Network POJ - 3694 (LCA+tarjan+桥)

题目链接:https://vjudge.net/problem/POJ-3694

具体思路:首先可以通过缩点的方式将整个图变成一个树,并且树的每条边是桥,但是我们可以利用dfn数组将整个图变成树,这样就可以省去缩点的过程了,同时lca的作用。假设有如下情况。

f->a    f->b,这是缩点之后的,如果在a,b之间加一条边的话,从a->a和b的最近公共祖先节点-> b 之间的桥都会去除,这个时候就需要用到lca了/

AC代码(折磨了我两天--):

  1 #include<iostream>
  2 #include<stack>
  3 #include<queue>
  4 #include<map>
  5 #include<stdio.h>
  6 #include<cstring>
  7 #include<string>
  8 #include<iomanip>
  9 #include<vector>
 10 #include<cmath>
 11 #include<algorithm>
 12 using namespace std;
 13 # define ll long long
 14 # define maxn 500000+1010
 15 # define inf 0x3f3f3f3f
 16 int head[maxn],dfn[maxn],low[maxn];
 17 int judge[maxn];
 18 int father[maxn];
 19 int edge,num,n,m,ans;
 20 struct node
 21 {
 22     int to;
 23     int nex;
 24 } q[maxn];
 25 void init()
 26 {
 27     memset(judge,0,sizeof(judge));
 28     memset(head,-1,sizeof(head));
 29     memset(dfn,0,sizeof(dfn));
 30     memset(low,0,sizeof(low));
 31     for(int i=1; i<=n; i++)
 32     {
 33         father[i]=i;
 34     }
 35     edge=0;
 36     num=0;
 37     ans=0;
 38 }
 39 void addedge(int fr,int to)
 40 {
 41     q[edge].to=to;
 42     q[edge].nex=head[fr];
 43     head[fr]=edge++;
 44 }
 45 void tarjan(int u,int root)
 46 {
 47     low[u]=dfn[u]=++num;
 48     dfn[u]=dfn[root]+1;//建造树的过程。
 49     for(int i=head[u]; i!=-1; i=q[i].nex)
 50     {
 51         int temp=q[i].to;
 52         if(temp==root)continue;//如果 1-> 2 这条边已经访问过的话,2->1 就没有必要访问了,如果在访问的话会出问题的。
 53         if(dfn[temp]==0)
 54         {
 55             father[temp]=u;
 56             tarjan(temp,u);
 57             low[u]=min(low[u],low[temp]);
 58             if(low[temp]>dfn[u])//判断桥的方法,注意比较的是前一个的时间戳
 59             {
 60                 ans++;
 61                 judge[temp]=1;
 62             }
 63         }
 64         else if(temp!=u)
 65         {
 66             low[u]=min(low[u],dfn[temp]);
 67         }
 68     }
 69 }
 70 void lca(int t1,int t2)
 71 {
 72 
 73     while(dfn[t1]<dfn[t2])
 74     {
 75         if(judge[t2])ans--,judge[t2]=0;
 76         t2=father[t2];
 77     }
 78     while(dfn[t1]>dfn[t2])
 79     {
 80         if(judge[t1])
 81         {
 82             ans--;
 83             judge[t1]=0;
 84         }
 85         t1=father[t1];
 86     }
 87     while(t1!=t2)
 88     {
 89         if(judge[t1])ans--;
 90         if(judge[t2])ans--;
 91         judge[t1]=0;
 92         judge[t2]=0;
 93         t1=father[t1];
 94         t2=father[t2];
 95     }
 96 }
 97 int main()
 98 {
 99     int Case=0;
100     while(~scanf("%d %d",&n,&m)&&(n+m))
101     {
102         init();
103         int t1,t2;
104         for(int i=1; i<=m; i++)
105         {
106             scanf("%d %d",&t1,&t2);
107             addedge(t1,t2);
108             addedge(t2,t1);
109         }
110         tarjan(1,0);
111         int t;
112         printf("Case %d:\n",++Case);
113         scanf("%d",&t);
114         while(t--)
115         {
116             scanf("%d %d",&t1,&t2);
117             lca(t1,t2);
118             printf("%d\n",ans);
119         }
120         printf("\n");
121     }
122     return 0;
123 }

 

posted @ 2018-11-23 17:47  Let_Life_Stop  阅读(246)  评论(0编辑  收藏  举报