hdu 4635 Strongly connected

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4635

大意:给出一个简单有向图,问最多可以向图中添加几条边,并且保证图不是强连通

解法:图的最后形式肯定是两部分X和Y,且两部分之间要么只有X到Y的边,要么只有Y到X的边,并且X和Y都是完全图,此时有边数为

   ans = x*(x-1)+y*(y-1)+x*y,因为x+y = n,化简得:ans = n*n-n-x*y,当x尽可能小的时候,ans才会尽可能的大,所以

   首先求强连通分量缩点,然后找到出度或入度为0(一定存在)中点数最少的强连通分量作为X,最后的答案还需要减去原来就存在的边

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 using namespace std;
 6 
 7 const int Max = 200001;
 8 
 9 int stop, visitnum, cnt;
10 int dfn[Max], low[Max], stack[Max], belong[Max], num[Max];
11 int n, m, dego[Max], degi[Max];
12 bool use[Max];
13 vector < vector <int> > a(Max);
14 
15 void tarjan(int i)
16 {
17     int j;
18     dfn[i] = low[i] = ++visitnum;
19     use[i] = 1;
20     stack[++stop] = i;
21     for (int k=0; k<a[i].size(); k++)
22     {
23         j = a[i][k];
24         if (!dfn[j]) {
25             tarjan(j);
26             low[i] = min(low[i], low[j]);
27         }else if (use[j]) low[i] = min(low[i], dfn[j]);
28     }
29     if (dfn[i] == low[i])
30     {
31         cnt ++; 
32         do {
33             j = stack[stop--];
34             use[j] = 0;
35             belong[j] = cnt;
36             num[cnt] ++;
37         } while (j != i);
38     }
39 }
40 
41 long long calc()
42 {
43     if (cnt == 1) return -1;
44     for (int i=1; i<=n; i++)
45         for (int j=0; j<a[i].size(); j++) 
46             if (belong[i] != belong[a[i][j]]) {
47                 dego[belong[i]] ++; 
48                 degi[belong[a[i][j]]] ++;
49             }
50     int ans = Max;
51     for (int i=1; i<=cnt; i++)
52         if (!dego[i] || !degi[i]) ans = min(ans, num[i]);
53     long long p = n;
54     return p*p-p-ans*(p-ans)-m;
55 }
56 
57 void solve()
58 {
59     cnt = stop = visitnum = 0; 
60     memset(dfn, 0, sizeof(dfn));
61     memset(use, 0, sizeof(use));
62     memset(num, 0, sizeof(num));
63     memset(dego, 0, sizeof(dego));
64     memset(degi, 0, sizeof(degi));
65     for (int i=1; i<=n; i++)
66         if (!dfn[i]) tarjan(i);
67 }
68 
69 int main()
70 {
71     int T; scanf("%d", &T);
72     for (int t=1; t<=T; t++)
73     {
74         for (int i=0; i<Max; i++) a[i].clear();
75         scanf("%d%d", &n, &m);
76         for (int i=0; i<m; i++)
77         {
78             int x, y; scanf("%d%d", &x, &y);
79             a[x].push_back(y);
80         }
81         solve();
82         cout << "Case " << t << ": " << calc() << endl;
83     }
84     return 0;
85 }
View Code

 

 

posted @ 2013-08-03 15:11  sxqqslf  阅读(123)  评论(0编辑  收藏  举报