Hdu 4635 Strongly connected

题目链接:

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

题目描述:

  给出一个有向图,问最大加入多少条边使原图还是不能强连通?

解题思路:

  加入的边是最多的,那么肯定是强连通图减去一条边,可以先把图中的强连通分支找出来,然后把其中一个分支(包含x个点)独立出来,其余的点(包含n-x点)只和这x个点连通,但是不能双向连通。这样既可以得出图中一共有x*(x-1) + (n-x)*(n-x-1) + (n-1)*x条边,化简后可得n*(n-1) - x*(n-x),可知当x越小最后得到的图中边数越多。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 typedef long long LL;
  8 const int maxn = 100005;
  9 const int INF = 0x3f3f3f3f;
 10 struct node
 11 {
 12     int to, next;
 13 } edge[maxn];
 14 int head[maxn], low[maxn], dfn[maxn], stack[maxn], num[maxn];
 15 int instack[maxn], id[maxn], out[maxn], in[maxn], cnt, tot, top, ntime;
 16 
 17 void init ()
 18 {
 19     cnt = tot = top = ntime = 0;
 20     memset (in, 0, sizeof(in));
 21     memset (id, 0, sizeof(id));
 22     memset (low, 0, sizeof(low));
 23     memset (dfn, 0, sizeof(dfn));
 24     memset (num, 0, sizeof(num));
 25     memset (out, 0, sizeof(out));
 26     memset (head, -1, sizeof(head));
 27     memset (stack, 0, sizeof(stack));
 28     memset (instack, 0, sizeof(instack));
 29 }
 30 void Add (int from, int to)
 31 {
 32     edge[tot].to = to;
 33     edge[tot].next = head[from];
 34     head[from] = tot ++;
 35 }
 36 void Tarjan (int u)
 37 {
 38     low[u] = dfn[u] = ++ ntime;
 39     stack[top++] = u;
 40     instack[u] = 1;
 41     for (int i=head[u]; i!=-1; i=edge[i].next)
 42     {
 43         int v = edge[i].to;
 44         if (!dfn[v])
 45         {
 46             Tarjan(v);
 47             low[u] = min (low[u], low[v]);
 48         }
 49         else if (instack[v])
 50             low[u] = min (low[u], dfn[v]);
 51     }
 52     if (dfn[u] == low[u])
 53     {
 54         cnt ++;
 55         while (1)
 56         {
 57             int v = stack[--top];
 58             instack[v] = 0;
 59             num[cnt] ++;
 60             id[v] = cnt;
 61             if (v == u)
 62                 break;
 63         }
 64     }
 65 }
 66 int main ()
 67 {
 68     int t, m, u, v, l = 0;
 69     LL  n;
 70     scanf ("%d", &t);
 71     while (t --)
 72     {
 73         init ();
 74         scanf ("%lld %d", &n, &m);
 75         for (int i=1; i<=m; i++)
 76         {
 77             scanf ("%d %d", &u, &v);
 78             Add (u, v);
 79         }
 80         for (int i=1; i<=n; i++)
 81             if (!dfn[i])
 82                 Tarjan (i);
 83         if (cnt == 1)
 84         {
 85             printf ("Case %d: -1\n", ++l);
 86             continue;
 87         }
 88         for (int i=1; i<=n; i++)
 89             for (int j=head[i]; j!=-1; j=edge[j].next)
 90             {
 91                 u = id[i];
 92                 v = id[edge[j].to];
 93                 if (u != v)
 94                 {
 95                     in[u] ++;
 96                     out[v] ++;
 97                 }
 98             }
 99         LL x, ans = 0;
100         x = n * (n - 1) - m;
101         for (int i=1; i<=cnt; i++)
102             if (!in[i] || !out[i])
103                 ans = max (ans, x - num[i] * (n-num[i]));
104         printf ("Case %d: %lld\n", ++l, ans);
105     }
106     return 0;
107 }

 

你可能感兴趣的:(connect)