loj 1210 (求最少的加边数使得图变成强连通)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1210

思路:首先是缩点染色,然后重建并且统计新图中的每个点的入度和出度,于是答案就是max(入度为0的点的个数, 出度为0的点的个数,这里有一个trick就是如果scc_count == 1,那么应该输出0.

loj 1210 (求最少的加边数使得图变成强连通)
  1 #include <iostream>

  2 #include <cstdio>

  3 #include <cstring>

  4 #include <algorithm>

  5 #include <stack>

  6 using namespace std;

  7 

  8 const int MAXN = (20000 + 20);

  9 int n, m, NE;

 10 struct Edge {

 11     int v, next;

 12 } edge[MAXN << 2];

 13 

 14 int head[MAXN];

 15 void Insert(int u, int v)

 16 {

 17     edge[NE].v = v;

 18     edge[NE].next = head[u];

 19     head[u] = NE++;

 20 }

 21 

 22 int cnt, scc_count;

 23 int low[MAXN], dfn[MAXN], color[MAXN];

 24 bool mark[MAXN];

 25 stack<int >S;

 26 

 27 void Tarjan(int u)

 28 {

 29     low[u] = dfn[u] = ++cnt;

 30     mark[u] = true;

 31     S.push(u);

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

 33         int v = edge[i].v;

 34         if (dfn[v] == 0) {

 35             Tarjan(v);

 36             low[u] = min(low[u], low[v]);

 37         } else if (mark[v]) {

 38             low[u] = min(low[u], dfn[v]);

 39         }

 40     }

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

 42         scc_count++;

 43         int v;

 44         do {

 45             v = S.top();

 46             S.pop();

 47             mark[v] = false;

 48             color[v] = scc_count;

 49         } while (u != v);

 50     }

 51 }

 52 

 53 int Indegree[MAXN], Outdegree[MAXN];

 54 

 55 int main()

 56 {

 57     int _case, t = 1;

 58     scanf("%d", &_case);

 59     while (_case--) {

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

 61         NE = 0;

 62         memset(head, -1, sizeof(head));

 63         while (m--) {

 64             int u, v;

 65             scanf("%d %d", &u, &v);

 66             Insert(u, v);

 67         }

 68         cnt = scc_count = 0;

 69         memset(dfn, 0, sizeof(dfn));

 70         memset(mark, false, sizeof(mark));

 71         for (int i = 1; i <= n; i++) {

 72             if (dfn[i] == 0) Tarjan(i);

 73         }

 74         memset(Indegree, 0, sizeof(Indegree));

 75         memset(Outdegree, 0, sizeof(Outdegree));

 76         for (int u = 1; u <= n; u++) {

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

 78                 int v = edge[i].v;

 79                 if (color[u] != color[v]) {

 80                     Indegree[color[v]]++;

 81                     Outdegree[color[u]]++;

 82                 }

 83             }

 84         }

 85         int ans1 = 0, ans2 = 0;

 86         for (int i = 1; i <= scc_count; i++) {

 87             if (Indegree[i] == 0) ans1++;

 88             if (Outdegree[i] == 0) ans2++;

 89         }

 90         printf("Case %d: ", t++);

 91         if (scc_count == 1) {

 92             puts("0");

 93         } else 

 94             printf("%d\n", max(ans1, ans2));

 95     }

 96     return 0;

 97 }

 98 

 99 

100         
View Code

 

你可能感兴趣的:(OJ)