hdu 3394 Railway

这是一道用tarjin求双连通分量的题;

其中,不需要修的道路就是桥的数目;

在图的每个极大环中,如果点的数目小于边的数目,显然这个环中含有子环,并且这个环的边数就是这个环中有冲突的边的数目;

如果点的数模等于边的数目,那就没有冲突;

代码:

 1 #include<cstdio>
 2 #include<vector>
 3 #include<cstring>
 4 using namespace std;
 5 #define maxn 10005
 6 
 7 vector<int>g[maxn];
 8 int block[maxn],top,stack[maxn],dfn[maxn],low[maxn],index,res1,res2;
 9 bool instack[maxn],vis[maxn];
10 
11 void count_edge()
12 {
13     memset(vis,0,sizeof vis);
14     for(int i=1; i<=block[0]; i++)
15         vis[block[i]]=1;
16     int sum=0;
17     for(int i=1; i<=block[0]; i++)
18     {
19         int w=block[i];
20         for(int j=0; j<g[w].size(); j++)
21             if(vis[g[w][j]])
22                 sum++;
23     }
24     sum/=2;//这个块中的边数
25     if(sum<block[0])
26         res1+=sum;
27     if(sum>block[0])
28         res2+=sum;
29 }
30 void tarjan(int v)
31 {
32     dfn[v]=low[v]=++index;
33     stack[++top]=v;
34     instack[v]=true;
35     for(int i=0; i<g[v].size(); i++)
36     {
37         int w=g[v][i];
38         if(!dfn[w])
39         {
40             tarjan(w);
41             low[v]=min(low[v],low[w]);
42             if(low[w]>=dfn[v])
43             {
44                 block[0]=0;
45                 while(1)
46                 {
47                     block[++block[0]]=stack[top];
48                     instack[stack[top]]=0;
49                     if(stack[top--]==w)break;
50                 }
51                 block[++block[0]]=v;
52                 count_edge();
53             }
54         }
55         else if(instack[w])
56             low[v]=min(low[v],dfn[w]);
57     }
58 }
59 
60 int main ()
61 {
62     int n,m,x,y;
63     while(scanf("%d%d",&n,&m)==2 && n+m)
64     {
65         for(int i=0; i<n; i++)g[i].clear();
66         for(int i=0; i<m; i++)
67         {
68             scanf("%d%d",&x,&y);
69             g[x].push_back(y);
70             g[y].push_back(x);
71         }
72         memset(dfn,0,sizeof dfn);
73         memset(low,0,sizeof low);
74         memset(instack,0,sizeof instack);
75         top=index=res1=res2=0;
76         for(int i=0; i<n; i++)if(!dfn[i])tarjan(i);
77         printf("%d %d\n",res1,res2);
78     }
79     return 0;
80 }
View Code

 

posted @ 2013-09-05 13:56  Yours1103  阅读(177)  评论(0编辑  收藏  举报