题意:
给出n个点和他们之间的一些关系..
问加多少条边可以使所有的点变成强连通分量..
思路:
根据题意就可以知道有这个推理:
原图缩点后的有向无环图..
出度为0的点和入度为0的点中个数少的那些点向个数多的那些点连线..
可以使森林变成强连通分量..
Tips:
注意如果缩点后变成一个点了..
则入度为0和出度为0的点的个数都是1 但是实际上已经是强连通分量..不需要连线了..
所以答案应该是0
Code:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }