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

 

posted @ 2013-09-25 11:05  ihge2k  阅读(304)  评论(0编辑  收藏  举报