【HDU3849】求无向图的割边

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3849

 

题目大意:给你一个关系网,问你那两个人是关键关系,即在整个关系网中起到链接作用,不可失去,这样对应到无向图中不就是要你求哪些边不在强连通分量中吗,即不在任何环中的边。

 

解题思路: 利用tarjan算法的变形,以前用tarjan求的是有向图的强连通分量,这个是无向图,所以要进行相应的变形。

 1、 首先,要求割边则对应的图必须是连通图,如果不是连通图那么割边就是0.

 2、开始WA了几次,因为我开始这么想:一条边连接的两个顶点只要在不同的连通分量中(low[]值不同),那么这条边就是割边,好像想想有道理唉?这样是错的,因为当出现两个强连通分量共边(即理解成两个环共边时),两个顶点的low[]值可能不同。 

割边的必要条件:low[u]!=low[v]

割边的充分必要条件:low[u]>dfn[v] || low[v]>dfn[u]。

 

View Code
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <map>
 4 #include <algorithm>
 5 #include <cstring>
 6 using namespace std;
 7 
 8 const int maxn=222222;
 9 int  dfn[maxn], low[maxn], head[maxn];
10 int  reach[maxn], next[maxn];
11 int top, Index, edge;
12 
13 struct node
14 {
15     char s[20];
16     friend bool operator <(const node &A, const node &B)
17     {
18         return strcmp(A.s,B.s)<0;
19     }
20 };
21 map<node,int>mp;
22 
23 struct Node
24 {
25     node x, y;
26     int flag;
27 }f[maxn];
28 
29 void init()
30 {
31     memset(head,-1,sizeof(head));
32     memset(dfn,0,sizeof(dfn));
33     edge=0;
34 }
35 
36 void addedge(int u, int v)
37 {
38     reach[edge]=v, next[edge]=head[u], head[u]=edge++;
39 }
40 
41 void tarjan(int u, int fa)
42 {
43     dfn[u]=low[u]=++Index;
44     for(int i=head[u]; i>=0; i=next[i])
45     {
46         int v=reach[i];
47         if(v==fa) continue;
48         if(!dfn[v]) tarjan(v,u), low[u]=min(low[u],low[v]);
49         else low[u]=min(low[u],dfn[v]);
50     }
51 }
52 
53 int main()
54 {
55     int n, m, T;
56     cin >> T;
57     while(T--)
58     {
59         int id=0;
60         mp.clear();
61         scanf("%d%d",&n,&m);
62         init();
63         for(int i=0; i<m; i++)
64         {
65             f[i].flag=0;
66             scanf("%s%s",&f[i].x.s,&f[i].y.s);
67             if(mp.find(f[i].x)==mp.end()) mp[f[i].x]=++id;
68             if(mp.find(f[i].y)==mp.end()) mp[f[i].y]=++id;
69             int u=mp[f[i].x], v=mp[f[i].y];
70             addedge(u,v), addedge(v,u);
71         }
72         tarjan(1,-1);
73         bool ok=true;
74         for(int i=1; i<=n; i++)
75             if(!dfn[i]){  ok=false; break;  }
76         if(!ok) puts("0");
77         else
78         {
79             int ans=0;
80             for(int i=0; i<m; i++)
81             {
82                 int u=mp[f[i].x], v=mp[f[i].y];
83                 if(low[u]>dfn[v]||low[v]>dfn[u]) ans++, f[i].flag=1; ///!!!
84             }
85             printf("%d\n",ans);
86             for(int i=0; i<m; i++)
87                 if(f[i].flag) printf("%s %s\n",f[i].x.s,f[i].y.s);
88         }
89     }
90     return 0;
91 }

 

posted @ 2013-04-29 19:16  Mr. Ant  阅读(626)  评论(0编辑  收藏  举报