poj2186Popular Cows【强连通】【debug两小时】
这个题我调试两个小时,快调哭了都
写一下心得
大意:告诉你一群牛 有n头 (n<10^4)
然后告诉你m对羡慕关系 如 a牛羡慕b牛
并且羡慕可以传递 如a羡慕b b羡慕c 则a羡慕c
现在问有多少只牛是被所有的牛羡慕的
分析:我的第一个思路是遍历每个牛 然后从每个牛建立反向边 然后dfs看能否扫到所有的牛 但是这样时间复杂度O(n*(n + e) ) 承受不住
后来想到可以像flody传递闭包那样但是同样时间复杂度承受
后来想到这个可以强连通一下子
我们首先想这么一个问题
对于一个有向无环图
满足一个牛被所有牛都羡慕的条件是 : 1 图连通 2 该牛的出度为零(因为他是被所有牛都羡慕的那只 然后如果他再羡慕其他的牛 就会形成环)
对于本题是有环的 用强连通 进行缩点 变成一个有向无环图 再根据那俩条件进行判定即可
但是写的时候 首先是我把图中有孤立点这种情况忽略了
然后就是 脑残的break之后……想起来就心痛啊
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int maxn = 50005; 7 8 int n, m; 9 int tot, cnt; 10 struct Node { 11 int to, next; 12 }e[maxn]; 13 int head[maxn]; 14 15 void add(int u, int v) { 16 e[tot].to = v; 17 e[tot].next = head[u]; 18 head[u] = tot++; 19 } 20 int s[maxn]; 21 int ins[maxn]; 22 int sc; 23 int ans; 24 int num[maxn]; 25 26 int low[maxn], dfn[maxn]; 27 28 void init() { 29 tot = 1; 30 memset(head, 0, sizeof(head)); 31 memset(low, 0, sizeof(low)); 32 memset(dfn, 0, sizeof(dfn)); 33 memset(ins, 0, sizeof(ins)); 34 memset(num, 0, sizeof(num)); 35 cnt = 1; 36 sc = 0; 37 ans = 0; 38 } 39 40 void dfs(int u) { 41 s[sc++] = u; 42 ins[u] = 1; 43 for(int i = head[u]; i; i = e[i].next) { 44 int v = e[i].to; 45 if(!dfn[v]) { 46 dfn[v] = low[v] = cnt++; 47 dfs(v); 48 low[u] = min(low[u], low[v]); 49 } else if(ins[v] && !num[v]) { 50 low[u] = min(low[u], dfn[v]); 51 } 52 } 53 if(low[u] == dfn[u]) { 54 ans++; 55 int x; 56 do { 57 x = s[--sc]; 58 num[x] = ans; 59 ins[x] = 0; 60 } while(x != u); 61 } 62 63 } 64 int outed[maxn]; 65 66 int main() { 67 int u, v; 68 while(EOF != scanf("%d %d",&n, &m) ) { 69 init(); 70 for(int i = 1; i <= m; i++) { 71 scanf("%d %d",&u, &v); 72 add(u, v); 73 } 74 for(int i = 1; i <= n; i++) { 75 if(!dfn[i]) { 76 dfn[i] = low[i] = cnt++; 77 dfs(i); 78 } 79 } 80 // for(int i = 1; i <= n; i++) { 81 // printf("%d ", num[i]); 82 // } puts(""); 83 int ans_num = -1; 84 memset(outed, 0, sizeof(outed)); 85 for(int i = 1; i <= n; i++) { 86 // printf("i = %d\n", i); 87 if(num[i] == 0) { 88 ans_num = 0; 89 break; 90 } 91 for(int j = head[i]; j ; j = e[j].next) { 92 int x = e[j].to; 93 if(num[i] != num[x]) { 94 outed[num[i]]++; 95 } 96 } 97 } 98 // for(int i = 1; i <= n; i++) { 99 // printf("*%d ", outed[i]); 100 // } puts(""); 101 // printf("ans = %d\n", ans); 102 int flag = 0; 103 if(ans_num != 0) { 104 ans_num = 0; 105 int ax = 0; 106 for(int i = 1; i <= ans; i++) { 107 if(outed[i] == 0) { 108 flag++; 109 if(flag >= 2) { 110 ans_num = 0; 111 break; 112 } 113 ax = i; 114 } 115 } 116 if(flag < 2) { 117 for(int i = 1; i <= n; i++) { 118 if(num[i] == ax) { 119 ans_num++; 120 } 121 } 122 } 123 } 124 printf("%d\n", ans_num); 125 } 126 return 0; 127 }