Hdu 2767 把森林变成强连通分量.cpp

题意:

  给出n个点和他们之间的一些关系..

  问加多少条边可以使所有的点变成强连通分量..

 

思路:

  根据题意就可以知道有这个推理:

    原图缩点后的有向无环图..

    出度为0的点和入度为0的点中个数少的那些点向个数多的那些点连线..

    可以使森林变成强连通分量..

 

Tips:

  注意如果缩点后变成一个点了..

  则入度为0和出度为0的点的个数都是1 但是实际上已经是强连通分量..不需要连线了..

  所以答案应该是0

 

Code:

View Code
  1 #include <stdio.h>

  2 #include <cstring>

  3 #include <algorithm>

  4 using namespace std;

  5 const int INF = 0x1f1f1f1f;

  6 #define clr(x) memset(x, 0, sizeof(x))

  7 const int MAXN = 20010;

  8 

  9 struct Edge

 10 {

 11     int to;

 12     int next;

 13 }edge[10000010];

 14 int head[MAXN];

 15 int tot;

 16 

 17 void add(int s, int u)

 18 {

 19     edge[tot].to = u;

 20     edge[tot].next = head[s];

 21     head[s] = tot++;

 22 }

 23 

 24 int dfn[MAXN], low[MAXN];

 25 int ins[MAXN], sta[MAXN], col[MAXN];

 26 int ti, top, cnt;

 27 int n;

 28 

 29 void tarjan(int u)

 30 {

 31     int i, k;

 32     dfn[u] = low[u] = ++ti;

 33     ins[u] = 1;

 34     sta[++top] = u;

 35     for(i = head[u]; i != -1; i = edge[i].next) {

 36         k = edge[i].to;

 37         if(dfn[k] == 0) {

 38             tarjan(k);

 39             low[u] = min(low[u], low[k]);

 40         } else if(ins[k]) {

 41             low[u] = min(low[u], dfn[k]);

 42         }

 43     }

 44     if(dfn[u] == low[u]) {

 45         cnt++;

 46         do

 47         {

 48             k = sta[top--];

 49             col[k] = cnt;

 50             ins[k] = 0;

 51         }while(u != k);

 52     }

 53 

 54 }

 55 

 56 void solve_ta()

 57 {

 58     int i, k;

 59     ti = top = cnt = 0;

 60     clr(dfn);

 61     for(i = 1; i <= n; ++i)

 62         if(!dfn[i])

 63             tarjan(i);

 64 }

 65 

 66 int ans;

 67 int in[MAXN], out[MAXN];

 68 void solve()

 69 {

 70     int i, j, k;

 71     ans = 0;

 72     clr(in), clr(out);

 73     solve_ta();

 74 

 75     for(i = 1; i <= n; ++i) {

 76         for(j = head[i]; j != -1; j = edge[j].next) {

 77             k = edge[j].to;

 78             if(col[i] != col[k]) {

 79                 in[col[k]]++;

 80                 out[col[i]]++;

 81             }

 82         }

 83     }

 84 

 85     int tmpa = 0, tmpb = 0;

 86     for(i = 1; i <= cnt; ++i) {

 87         if(in[i] == 0) tmpa++;

 88         if(out[i] == 0) tmpb++;

 89     }

 90 

 91     ans = max(tmpa, tmpb);

 92     if(cnt == 1) ans = 0;

 93 }

 94 

 95 int main()

 96 {

 97     int i, j, k;

 98     int a, b, T, m;

 99     scanf("%d", &T);

100     while(T--)

101     {

102         tot = 0;

103         memset(head, 0xff, sizeof(head));

104 

105         scanf("%d %d", &n, &m);

106         while(m--) {

107             scanf("%d %d", &a, &b);

108             add(a, b);

109         }

110         solve();

111         printf("%d\n", ans);

112     }

113     return 0;

114 }

 

 

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2767

你可能感兴趣的:(HDU)