poj3352 road construction tarjan求双连通分量
填坑……链接:http://poj.org/problem?id=3352
题意:求出图中再加上几条边会全部边双连通。
思路大概就是求出图中所有的双连通分量,然后像$SCC$一样缩点,缩完后每两个双连通分量再连边即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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\n",(num+1)>>1); 65 return 0; 66 } 67 int sb=haha(); 68 int main(){;}
只要是活着的东西,就算是神我也杀给你看。