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 }