【强连通分量+缩点】 POJ 2186 Popular Cows

来源:互联网 发布:photoshop cc mac 编辑:程序博客网 时间:2024/04/30 00:55

先求出强连通,再缩点。然后求一下出度为0的个数,如果出度为0的点只有一个,那个点所对应的集合个数就是答案,否则答案就是0。。

#include <iostream>  #include <queue>  #include <stack>  #include <map>  #include <set>  #include <bitset>  #include <cstdio>  #include <algorithm>  #include <cstring>  #include <climits>  #include <cstdlib>#include <cmath>#include <time.h>#define maxn 10005#define maxm 50005#define eps 1e-10#define mod 1000000009#define INF 99999999  #define lowbit(x) (x&(-x))  //#define lson o<<1, L, mid  //#define rson o<<1 | 1, mid+1, R  typedef long long LL;//typedef int LL;using namespace std;int H[maxn], NEXT[maxm], V[maxm];int h[maxn], next[maxm], v[maxm];int dfn[maxn], low[maxn], id[maxn];int ins[maxn], w[maxn], out[maxn];stack<int> s;int scc_cnt, top, n, m;void init(void){top = scc_cnt = 0;memset(h, -1, sizeof h);memset(H, -1, sizeof H);memset(w, 0, sizeof w);memset(ins, 0, sizeof ins);memset(dfn, 0, sizeof dfn);memset(out, 0, sizeof out);}void scanf(int &x){x = 0;char ch = getchar();while(ch == ' ' || ch == '\n') ch = getchar();while(ch >= '0' && ch <= '9') x=x*10+ch-'0', ch = getchar();}void read(void){int a, b, cnt = 0;while(m--) {//scanf("%d%d", &a, &b);scanf(a), scanf(b);NEXT[cnt] = H[a], H[a] = cnt, V[cnt] = b, cnt++;}}void tarjan(int u){dfn[u] = low[u] = ++top;s.push(u), ins[u] = 1;for(int e = H[u]; ~e; e = NEXT[e])if(!dfn[V[e]]) {tarjan(V[e]);low[u] = min(low[u], low[V[e]]);}else if(ins[V[e]]) low[u] = min(low[u], dfn[V[e]]);if(dfn[u] == low[u]) {int tmp = s.top(); s.pop(), ins[tmp] = 0;++scc_cnt;while(tmp != u) {id[tmp] = scc_cnt;tmp = s.top();s.pop();ins[tmp] = 0;}id[tmp] = scc_cnt;}}void narrow(void){int cnt = 0;for(int i = 1; i <= n; i++)for(int e = H[i]; ~e; e = NEXT[e])next[cnt] = h[id[i]], h[id[i]] = cnt, v[cnt] = id[V[e]], cnt++;}void work(void){int i, k = 0, ans = 0;for(i = 1; i <= n; i++)if(!dfn[i]) tarjan(i);narrow();for(i = 1; i <= n; i++) w[id[i]]++;for(i = 1; i <= scc_cnt; i++)for(int e = h[i]; ~e; e = next[e])if(v[e] != i)out[i]++;for(i = 1; i <= scc_cnt; i++) if(!out[i]) k++, ans = i;if(k == 1) printf("%d\n", w[ans]);else printf("0\n");}int main(void){while(scanf("%d%d", &n, &m)!=EOF) {init();read();work();}return 0;}


0 0
原创粉丝点击