poj 3352 Road Construction

本文详细介绍了一种基于BCC算法的实现方法,该算法用于求解无向图中的双连通分量。通过使用DFS深度优先搜索策略,文章展示了如何有效地找到图中的所有双连通分量,并进一步分析了这些分量之间的连接特性。

http://poj.org/problem?id=3352

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <queue>
  5 #include <algorithm>
  6 #define maxn 300000
  7 using namespace std;
  8 
  9 const int inf=1<<30;
 10 int head[maxn],dfn[maxn],low[maxn],belong[maxn],stack1[maxn],du[maxn];
 11 int e,bcc_clock,bcnt,top,N,E;
 12 bool vis[maxn],visi[maxn];
 13 
 14 struct node
 15 {
 16     int u,v,next;
 17 } p[maxn];
 18 
 19 void add(int u,int v)
 20 {
 21     p[e].u=u;
 22     p[e].v=v;
 23     p[e].next=head[u];
 24     head[u]=e++;
 25     p[e].u=v;
 26     p[e].v=u;
 27     p[e].next=head[v];
 28     head[v]=e++;
 29 }
 30 
 31 void tarjan(int u,int fa)
 32 {
 33     vis[u]=true;
 34     dfn[u]=low[u]=++bcc_clock;
 35     stack1[++top]=u;
 36     for(int i=head[u]; i!=-1; i=p[i].next)
 37     {
 38         int v=p[i].v;
 39         if(v==fa) continue;
 40         if(!dfn[v])
 41         {
 42             tarjan(v,u);
 43             low[u]=min(low[u],low[v]);
 44         }
 45         else if(vis[v])
 46         {
 47             low[u]=min(low[u],dfn[v]);
 48         }
 49     }
 50     if(dfn[u]==low[u])
 51     {
 52         bcnt++;
 53         int j;
 54         do
 55         {
 56             j=stack1[top--];
 57             vis[j]=false;
 58             belong[j]=bcnt;
 59         }
 60         while(j!=u);
 61     }
 62 }
 63 
 64 void deal()
 65 {
 66     bcc_clock=0,bcnt=0,top=0;
 67     memset(vis,false,sizeof(vis));
 68     memset(belong,0,sizeof(belong));
 69     memset(dfn,0,sizeof(dfn));
 70     tarjan(1,1);
 71 }
 72 
 73 void dfs(int u)
 74 {
 75     visi[u]=true;
 76     for(int i=head[u]; i!=-1; i=p[i].next)
 77     {
 78         int v=p[i].v;
 79         if(!visi[v])
 80         {
 81             if(belong[v]!=belong[u])
 82             {
 83                 ++du[belong[u]];
 84                 ++du[belong[v]];
 85             }
 86             dfs(v);
 87         }
 88     }
 89 }
 90 void inti()
 91 {
 92     memset(head,-1,sizeof(head));
 93     e=0;
 94 }
 95 
 96 int main()
 97 {
 98     while(cin>>N>>E)
 99     {
100         inti();
101         int x,y;
102         for(int i=0; i<E; i++)
103         {
104             scanf("%d%d",&x,&y);
105             add(x,y);
106         }
107         deal();
108         if(bcnt==1)
109         {
110             printf("0\n");
111             continue;
112         }
113         memset(du,0,sizeof(du));
114         int leaf=0;
115         memset(visi,false,sizeof(visi));
116         dfs(1);
117         for(int i=1; i<=bcnt; i++)
118         {
119             if(du[i]==1) leaf++;
120         }
121         printf("%d\n",(leaf+1)/2);
122     }
123     return 0;
124 }
View Code

 

转载于:https://www.cnblogs.com/fanminghui/p/3553720.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值