【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 }

 

你可能感兴趣的:(HDU)