HDU 2767 Proving Equivalences(强连通分量)

 

题目大意

 

一个有向图 n(1<=n<=20000) 个点 m(0<=m<=50000) 条边

问至少添加几条边,使得整个图是一个强连通图

 

做法分析

 

先缩点,然后找出 DAG 中入度为 0 的点的个数和出度为 0 的点的个数,输出较大者(PS:这是一个结论)

 

参考代码

 

HDU 2767
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <stack>
 5 
 6 using namespace std;
 7 
 8 struct Edge
 9 {
10     int en, next;
11     Edge() {}
12     Edge(int a, int b)
13     {
14         en=a, next=b;
15     }
16 } edge[50006];
17 int head[20006], tot;
18 int dfn[20006], low[20006], T, in[20006];
19 int id[20006], ind;
20 stack<int> S;
21 int t, n, m;
22 
23 void add_edge(int st, int en)
24 {
25     edge[tot]=Edge(en, head[st]);
26     head[st]=tot++;
27 }
28 
29 void tarjan(int u)
30 {
31     dfn[u]=low[u]=T++;
32     S.push(u), in[u]=1;
33     for(int e=head[u]; e!=-1; e=edge[e].next)
34     {
35         int v=edge[e].en;
36         if(dfn[v]==-1)
37         {
38             tarjan(v);
39             low[u]=min(low[u], low[v]);
40         }
41         else if(in[v] && dfn[v]<low[u]) low[u]=dfn[v];
42     }
43     if(dfn[u]==low[u])
44     {
45         ind++;
46         for(int v; v=S.top(); )
47         {
48             id[v]=ind;
49             in[v]=0, S.pop();
50             if(v==u) break;
51         }
52     }
53 }
54 
55 int main()
56 {
57     scanf("%d", &t);
58     for(int ca=1; ca<=t; ca++)
59     {
60         scanf("%d%d", &n, &m);
61         memset(head, -1, sizeof head);
62         tot=0;
63         for(int i=0, st, en; i<m; i++)
64         {
65             scanf("%d%d", &st, &en);
66             add_edge(st, en);
67         }
68         memset(in, 0, sizeof in);
69         memset(dfn, -1, sizeof dfn);
70         ind=-1;
71         while(!S.empty()) S.pop();
72         for(int i=1; i<=n; i++)
73             if(dfn[i]==-1) tarjan(i);
74         if(ind==0)
75         {
76             printf("0\n");
77             continue;
78         }
79         memset(dfn, 0, sizeof dfn);
80         memset(low, 0, sizeof low);
81         for(int i=1; i<=n; i++)
82         {
83             for(int e=head[i]; e!=-1; e=edge[e].next)
84             {
85                 if(id[i]!=id[edge[e].en]) dfn[id[i]]++, low[id[edge[e].en]]++;
86             }
87         }
88         int ans1=0, ans2=0;
89         for(int i=0; i<=ind; i++)
90         {
91             if(dfn[i]==0) ans1++;
92             if(low[i]==0) ans2++;
93         }
94         printf("%d\n", max(ans1, ans2));
95     }
96     return 0;
97 }

 

AC通道

 

HDU 2767 Proving Equivalences

 

 

 

posted @ 2013-03-17 00:30  jianzhang.zj  阅读(199)  评论(0编辑  收藏  举报