loj 1300( 边双联通 + 判奇圈 )

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27010

思路:首先Tarjan标记桥,然后对于dfs遍历整个图,我们可以得出一个简单的结论,就是如果一个双连通分量中存在奇圈,那么这个双连通分量中的所有点都可行,于是我们可以dfs染色判奇圈。

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 using namespace std;

 6 #define MAXN 22222

 7 

 8 struct Edge{

 9     int v,next;

10 }edge[MAXN<<1];

11 

12 int n,m,NE;

13 int head[MAXN];

14 

15 void Insert(int u,int v)

16 {

17     edge[NE].v=v;

18     edge[NE].next=head[u];

19     head[u]=NE++;

20 }

21 

22 int low[MAXN],dfn[MAXN],cnt;

23 bool bridge[MAXN<<1];

24 bool mark[MAXN];

25 

26 void Tarjan(int u,int father)

27 {

28     low[u]=dfn[u]=++cnt;

29     mark[u]=true;

30     for(int i=head[u];i!=-1;i=edge[i].next){

31         int v=edge[i].v;

32         if(v==father)continue;

33         if(dfn[v]==0){

34             Tarjan(v,u);

35             low[u]=min(low[u],low[v]);

36             if(low[v]>dfn[u]){

37                 bridge[i]=bridge[i^1]=true;

38             }

39         }else if(mark[v]){

40             low[u]=min(low[u],dfn[v]);

41         }

42     }

43 }

44 

45 int flag,ans;

46 int color[MAXN];

47 

48 void dfs(int u,int state)

49 {

50     cnt++;

51     color[u]=state;

52     for(int i=head[u];i!=-1;i=edge[i].next){

53         int v=edge[i].v;

54         if(bridge[i])continue;

55         if(color[v]&&color[u]==color[v]){

56             flag=1;

57         }else if(color[v]==0){

58             dfs(v,3-state);

59         }

60     }

61 }

62 

63 int main()

64 {

65     int _case,u,v,t=1;

66      scanf("%d",&_case);

67     while(_case--){

68         scanf("%d%d",&n,&m);

69         NE=0;

70         memset(head,-1,sizeof(head));

71         while(m--){

72             scanf("%d%d",&u,&v);

73             Insert(u,v);

74             Insert(v,u);

75         }

76         cnt=0;

77         memset(mark,false,sizeof(mark));

78         memset(dfn,0,sizeof(dfn));

79         memset(bridge,false,sizeof(bridge));

80         for(int i=0;i<n;i++)if(dfn[i]==0)Tarjan(i,i);

81         memset(color,0,sizeof(color));

82         ans=0;

83         for(int i=0;i<n;i++){

84             if(color[i]==0){

85                 flag=0;

86                 cnt=0;

87                 dfs(i,1);

88                 if(flag)ans+=cnt;

89             }

90         }

91         printf("Case %d: %d\n",t++,ans);

92     }

93     return 0;

94 }

95 

96 

97 

98         
View Code

 

你可能感兴趣的:(OJ)