poj3352 road construction tarjan求双连通分量

填坑……链接:http://poj.org/problem?id=3352

题意:求出图中再加上几条边会全部边双连通。

思路大概就是求出图中所有的双连通分量,然后像$SCC$一样缩点,缩完后每两个双连通分量再连边即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=1005;
 7 struct node
 8 {
 9     int from,to,next;
10 }edge[maxn<<1];
11 int head[maxn],tot;
12 void addedge(int u,int v)
13 {
14     edge[++tot]=(node){u,v,head[u]};head[u]=tot;
15 }
16 int dfn[maxn],low[maxn],cnt,bcnt,n,r,belong[maxn];
17 #include<stack>
18 stack<int>s;
19 void tarjan(int root,int id)
20 {
21     dfn[root]=low[root]=++cnt;s.push(root);
22     for(int i=head[root];i;i=edge[i].next)
23     {
24         int v=edge[i].to;
25         if((((i-1)>>1))!=id)
26         {
27             if(!dfn[v])
28             {
29                 tarjan(v,(i-1)>>1);
30                 low[root]=min(low[root],low[v]);
31             }
32             else low[root]=min(low[root],dfn[v]);
33         }
34     }
35     if(dfn[root]==low[root])
36     {
37         int k;bcnt++;
38         do
39         {
40             k=s.top();s.pop();
41             belong[k]=bcnt;
42         }while(k!=root);
43     }
44 }
45 int degree[maxn];
46 int haha()
47 {
48     scanf("%d%d",&n,&r);
49     for(int i=1;i<=r;i++)
50     {
51         int x,y;scanf("%d%d",&x,&y);
52         addedge(x,y);addedge(y,x);
53     }
54     for(int i=1;i<=n;i++)
55         if(!dfn[i])tarjan(i,-1);
56     for(int i=1;i<=tot;i++)
57     {
58         int u=edge[i].from,v=edge[i].to;
59         if(belong[u]!=belong[v])degree[belong[u]]++,degree[belong[v]]++;
60     }
61     int num=0;
62     for(int i=1;i<=bcnt&&bcnt>1;i++)
63         if(degree[i]<=2)num++;
64     printf("%d
",(num+1)>>1);
65     return 0;
66 }
67 int sb=haha();
68 int main(){;}
poj3352
原文地址:https://www.cnblogs.com/Loser-of-Life/p/7357286.html