标签:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 12598 | Accepted: 5330 |
Description
Input
Output
Sample Input
7 7 1 2 2 3 3 4 2 5 4 5 5 6 5 7
Sample Output
2
Hint
1 2 3Building new paths from 1 to 6 and from 4 to 7 satisfies the conditions.
+---+---+
| |
| |
6 +---+---+ 4
/ 5
/
/
7 +
1 2 3Check some of the routes:
+---+---+
: | |
: | |
6 +---+---+ 4
/ 5 :
/ :
/ :
7 + - - - -
1 /*这是一个63分的代码,因为没有注意到题目中的重边问题,以后要注意有重边的图和没有重边的图的tarjan求桥的算法,是不同的*/ 2 #include<iostream> 3 using namespace std; 4 #include<cstdio> 5 #define N 5001 6 #define R 10010 7 #include<stack> 8 #include<queue> 9 #include<cstring> 10 queue<int>que; 11 bool qiao[R]={0},visit[N]={0},visit_edge[R<<1]; 12 struct Edge{ 13 int u,v,last; 14 }edge[R*2]; 15 int head[N],du[N],f,r,father[N],dfn[N],low[N],topt=0,t=-1; 16 int ans[N]={0}; 17 void add_edge(int u,int v) 18 { 19 ++t; 20 edge[t].u=u; 21 edge[t].v=v; 22 edge[t].last=head[u]; 23 head[u]=t; 24 } 25 void input() 26 { 27 memset(head,-1,sizeof(head)); 28 int u,v; 29 scanf("%d%d",&f,&r); 30 for(int i=1;i<=r;++i) 31 { 32 scanf("%d%d",&u,&v); 33 add_edge(u,v); 34 add_edge(v,u); 35 } 36 r<<=1; 37 } 38 void tarjan(int u) 39 { 40 dfn[u]=low[u]=++topt; 41 for(int l=head[u];l!=-1;l=edge[l].last) 42 { 43 int v=edge[l].v; 44 if(!visit_edge[l]&&!visit_edge[l^1]) 45 { 46 visit_edge[l]=true; 47 if(!dfn[v]) 48 { 49 tarjan(v); 50 low[u]=min(low[u],low[v]); 51 if(low[v]>dfn[u]) qiao[l]=true; 52 } 53 else low[u]=min(low[u],dfn[v]); 54 } 55 } 56 } 57 void suo_dian() 58 { 59 for(int i=1;i<=f;++i) 60 { 61 if(!visit[i]) 62 { 63 ans[++ans[0]]=i; 64 que.push(i); 65 visit[i]=true; 66 while(!que.empty()) 67 { 68 int x=que.front(); 69 father[x]=i; 70 que.pop(); 71 for(int l=head[x];l!=-1;l=edge[l].last) 72 { 73 if(qiao[l]||visit[edge[l].v]) continue; 74 que.push(edge[l].v); 75 visit[edge[l].v]=true; 76 } 77 } 78 79 } 80 } 81 } 82 void re_jiantu() 83 { 84 for(int l=0;l<=r;++l) 85 { 86 if(father[edge[l].u]!=father[edge[l].v]) 87 { 88 du[father[edge[l].u]]++; 89 du[father[edge[l].v]]++; 90 } 91 } 92 } 93 int main() 94 { 95 freopen("rpaths.in","r",stdin); 96 freopen("rpaths.out","w",stdout); 97 input(); 98 for(int i=1;i<=f;++i) 99 { 100 if(!dfn[i]) 101 tarjan(i); 102 } 103 suo_dian(); 104 re_jiantu(); 105 int sum=0; 106 for(int i=1;i<=ans[0];++i) 107 if(du[ans[i]]==2) 108 sum++; 109 printf("%d\n",(sum+1)/2); 110 fclose(stdin);fclose(stdout); 111 return 0; 112 }
正确代码及模板:
1 #define N 5011 2 #include<iostream> 3 using namespace std; 4 #define M 10010 5 #include<cstdio> 6 #include<cstring> 7 struct Gra{ 8 int n,m,ans,head[N],topt,dfn[N],low[N],t,cnt[N]; 9 bool visit[M<<1]; 10 struct Edge{ 11 int v,last; 12 }edge[M<<1]; 13 void init(int f,int r) 14 {/*初始化不要在上面,上面只是声明,不是变量*/ 15 ans=0,topt=0,t=-1; 16 n=f;m=r; 17 memset(head,-1,sizeof(head)); 18 memset(dfn,0,sizeof(dfn)); 19 memset(low,0,sizeof(low)); 20 memset(cnt,0,sizeof(cnt)); 21 memset(visit,false,sizeof(visit)); 22 } 23 void add_edge(int x,int y) 24 { 25 ++t; 26 edge[t].v=y; 27 edge[t].last=head[x]; 28 head[x]=t; 29 } 30 void tarjan(int u) 31 { 32 dfn[u]=low[u]=++topt; 33 for(int l=head[u];l!=-1;l=edge[l].last) 34 { 35 if(visit[l]) continue; 36 visit[l]=visit[l^1]=true;/*找到无向边拆成的另一条边*/ 37 int v=edge[l].v; 38 if(!dfn[v]) 39 { 40 tarjan(v); 41 low[u]=min(low[v],low[u]); 42 } 43 else low[u]=min(low[u],dfn[v]);/*多次返祖*/ 44 } 45 } 46 void start() 47 { 48 for(int i=1;i<=n;++i) 49 if(!dfn[i]) 50 tarjan(i); 51 for(int i=1;i<=n;++i)/*处理缩点以后的图*/ 52 for(int l=head[i];l!=-1;l=edge[l].last) 53 { 54 int v=edge[l].v; 55 if(low[i]!=low[v]) 56 cnt[low[v]]++; 57 /*low[x]!=low[y]说明从low[y]回不到low[x],那么low[x]--low[y]是一条桥,因为tarjan中多次返祖*/ 58 } 59 for(int i=1;i<=n;++i) 60 if(cnt[i]==1) ans++;/*统计度数是1的叶子节点的数目*/ 61 printf("%d\n",(ans+1)>>1); 62 } 63 }G; 64 int main() 65 { 66 int n,m; 67 scanf("%d%d",&n,&m); 68 G.init(n,m); 69 int x,y; 70 for(int i=1;i<=m;++i) 71 { 72 scanf("%d%d",&x,&y); 73 G.add_edge(x,y); 74 G.add_edge(y,x); 75 } 76 G.start(); 77 return 0; 78 }
tarjan算法求桥双连通分量 POJ 3177 Redundant Paths
标签:
原文地址:http://www.cnblogs.com/c1299401227/p/5571315.html