首页 > 代码库 > HDU 2767:Proving Equivalences(强连通)

HDU 2767:Proving Equivalences(强连通)

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

题意:给出n个点m条边,问在m条边的基础上,最小再添加多少条边可以让图变成强连通。思路:强连通分量缩点后找入度为0和出度为0的点,因为在强连通图里面没有一个点的入度和出度都为0,所以取出度为0的点和入度为0的点中的最大值就是答案。(要特判强连通分量数为1的情况)

  1 #include <cstdio>  2 #include <algorithm>  3 #include <iostream>  4 #include <cstring>  5 #include <string>  6 #include <cmath>  7 #include <queue>  8 #include <vector>  9 #include <stack> 10 using namespace std; 11 #define N 20010 12 #define M 50010 13 struct node 14 { 15     int v, next, u; 16 }edge[M]; 17 int n, tot, cnt, num, head[N], dfn[N], low[N], belong[N], in[N], out[N]; 18 bool vis[N]; 19 stack<int> sta; 20  21 void init() 22 { 23     tot = 0; 24     num = 0; 25     cnt = 0; 26     while(!sta.empty()) sta.pop(); 27     memset(head, -1, sizeof(head)); 28     memset(vis, false, sizeof(vis)); 29     memset(low, 0, sizeof(low)); 30     memset(dfn, 0, sizeof(dfn)); 31     memset(belong, 0, sizeof(belong)); 32     memset(in, 0, sizeof(in)); 33     memset(out, 0, sizeof(out)); 34 } 35  36 void add(int u, int v) 37 { 38     edge[tot].next = head[u]; edge[tot].v = v; edge[tot].u = u; head[u] = tot++; 39 } 40  41 void tarjan(int u) 42 { 43     dfn[u] = low[u] = ++cnt; 44     sta.push(u); 45     vis[u] = true; 46     for(int i = head[u]; ~i; i = edge[i].next) { 47         int v = edge[i].v; 48         if(!dfn[v]) { 49             tarjan(v); 50             if(low[v] < low[u]) low[u] = low[v]; 51         } else { 52             if(vis[v] && low[u] > dfn[v]) low[u] = dfn[v]; 53         } 54     } 55     if(dfn[u] == low[u]) { 56         num++; 57         int top = 0; 58         while(top != u) { 59             top = sta.top(); 60             belong[top] = num; 61             vis[top] = 0; 62             sta.pop(); 63         } 64     } 65 } 66  67 int main() 68 { 69     int t; 70     scanf("%d", &t); 71     while(t--) { 72         init(); 73         int m; 74         scanf("%d%d", &n, &m); 75         for(int i = 0; i < m; i++) { 76             int u, v; 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             } 84         } 85         for(int u = 1; u <= n; u++) { 86             for(int i = head[u]; ~i; i = edge[i].next) { 87                 int v = edge[i].v; 88                 if(belong[u] != belong[v]) { 89                     in[belong[u]]++; 90                     out[belong[v]]++; 91                 } 92             } 93         } 94         int inn = 0, outt = 0; 95         for(int i = 1; i <= num; i++) { 96             if(in[i] == 0) inn++; 97             if(out[i] == 0) outt++; 98         } 99         int ans = max(inn, outt);100         if(num == 1) ans = 0;101         printf("%d\n", ans);102     }103     return 0;104 }

 

HDU 2767:Proving Equivalences(强连通)