/* *题目大意: * 在数学里面有两种关系,一种是充分条件,即对于集合p,q,p => q, * 另一种是等价关系,p => q && q =>p, 这两种关系都具有传递性,p * => q 可以对应到有节点p到节点q有一条边。问:给定一些集合的充分 * 性关系,确定出若让所有集合都等价,还需在添加最少的充分性条件。 *解题思路: * 有向图加最少边变强连通,模板题 */
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int MAXN = 20005; 7 8 typedef struct _node 9 { 10 int v, next; 11 }N; 12 N edge[MAXN * 3]; 13 int dfn[MAXN], low[MAXN], step; 14 int inS[MAXN], id[MAXN], scc, myS[MAXN], top; 15 int in[MAXN], out[MAXN], cntEdge, head[MAXN]; 16 17 void init() 18 { 19 cntEdge = step = scc = top = 0; 20 for(int i = 0; i < MAXN; i++) 21 { 22 head[i] = -1; 23 dfn[i] = low[i] = -1; 24 id[i] = -1; 25 in[i] = out[i] = 0; 26 inS[i] = 0; 27 } 28 } 29 30 void tarjan(int n) 31 { 32 dfn[n] = low[n] = ++step; 33 myS[top++] = n; 34 inS[n] = 1; 35 for(int f = head[n]; f != -1; f = edge[f].next) 36 { 37 int son = edge[f].v; 38 if(dfn[son] == -1) 39 { 40 tarjan(son); 41 low[n] = min(low[n], low[son]); 42 } 43 else if(inS[son] != 0) 44 low[n] = min(low[n], dfn[son]); 45 } 46 47 if(low[n] == dfn[n]) 48 { 49 int tmp; 50 do 51 { 52 tmp = myS[--top]; 53 inS[tmp] = 0; 54 id[tmp] = scc; 55 }while(myS[top] != n); 56 scc++; 57 } 58 } 59 60 void addEdge(int u, int v) 61 { 62 edge[cntEdge].v = v; 63 edge[cntEdge].next = head[u]; 64 head[u] = cntEdge++; 65 } 66 67 68 69 int main(void) 70 { 71 #ifndef ONLINE_JUDGE 72 freopen("inHDU2767.txt", "r", stdin); 73 #endif 74 75 int n, m, cas; 76 scanf("%d", &cas); 77 while(cas--) 78 { 79 scanf("%d %d", &n, &m); 80 init(); 81 int u, v; 82 for(int i = 0; i < m; i++) 83 { 84 scanf("%d %d", &u, &v); 85 addEdge(u, v); 86 } 87 88 for(int i = 1; i <= n; i++) 89 { 90 if(dfn[i] == -1) 91 tarjan(i); 92 } 93 for(int i = 1; i <= n; i++) 94 { 95 for(int j = head[i]; j != -1; j = edge[j].next) 96 { 97 u = i, v = edge[j].v; 98 if(id[u] == id[v]) 99 continue; 100 else 101 { 102 in[id[v]]++; 103 out[id[u]]++; 104 } 105 } 106 } 107 int inNum = 0, outNum = 0; 108 for(int i = 0; i < scc; i++) 109 { 110 if(!in[i]) 111 inNum++; 112 if(!out[i]) 113 outNum++; 114 } 115 if(scc >= 2) 116 printf("%d\n", max(inNum, outNum)); 117 else 118 printf("0\n"); 119 } 120 return 0; 121 }