【BZOJ】1051: [HAOI2006]受欢迎的牛(tarjan)
http://www.lydsy.com/JudgeOnline/problem.php?id=1051
这题还好~1A了。。但是前提还是看了题解的 囧。。。。。一开始认为是并查集,oh,不行,,无法维护和判断。。好吧。
看了题解后发现这是如何巧妙0v0!,我们将题目抽象为图,然后找出所有的环,你想啊,,,所有的换最后都有一条路径连向某一个环~那么恭喜这个环成为所有人的喜爱~~咳咳。。懂了吧。。判断这个最后的环用tarjan缩点后判断是否有且只有一个环没有连边出去,即出度为0,用前向星的就很好判断~~
#include <cstdio> #include <cstring> #include <string> #include <iostream> #include <cmath> #include <algorithm> using namespace std; #define rep(i, n) for(int i=0; i<(n); ++i) #define for1(i,a,n) for(int i=(a);i<=(n);++i) #define for2(i,a,n) for(int i=(a);i<(n);++i) #define for3(i,a,n) for(int i=(a);i>=(n);--i) #define for4(i,a,n) for(int i=(a);i>(n);--i) #define CC(i,a) memset(i,a,sizeof(i)) #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define read(a) a=getnum() #define print(a) printf("%d", a) inline int getnum() { int ret=0; char c; for(c=getchar(); c<'0' || c>'9'; c=getchar()); for(; c>='0' && c<='9'; c=getchar()) ret=ret*10+c-'0'; return ret; } const int N=10005, M=50005; int ihead[N], inext[M], to[M], cnt; int LL[N], FF[N], top, s[N], p[N], cyc, tot, vis[N], hav[N]; int p_ihead[N], p_inext[M], p_cnt; int n, m, ans; inline void add(const int &u, const int &v) { inext[++cnt]=ihead[u]; ihead[u]=cnt; to[cnt]=v; } void dfs(int u) { s[++top]=u; vis[u]=1; LL[u]=FF[u]=++tot; for(int i=ihead[u]; i; i=inext[i]) { if(!FF[to[i]]) { dfs(to[i]); LL[u]=min(LL[u], LL[to[i]]); } else if(vis[to[i]] && FF[to[i]]<LL[u]) LL[u]=FF[to[i]]; } if(LL[u]==FF[u]) { ++cyc; int r; do { r=s[top--]; p[r]=cyc; vis[r]=0; ++hav[cyc]; } while(r!=u); } } void rebuild() { for1(u, 1, n) { for(int i=ihead[u]; i; i=inext[i]) { if(p[u] != p[to[i]]) { p_inext[++p_cnt]=p_ihead[p[u]]; p_ihead[p[u]]=p_cnt; } } } } void tarjan() { for1(i, 1, n) if(!FF[i]) dfs(i); rebuild(); } void getans() { for1(i, 1, cyc) if(!p_ihead[i]) { if(ans) { ans=0; return; } else ans=hav[i]; } } int main() { int x, y; read(n); read(m); for1(i, 0, n+1) p[i]=i; rep(i, m) { read(x); read(y); add(x, y); } tarjan(); getans(); print(ans); return 0; }
Description
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。
Input
第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B)
Output
一个数,即有多少头牛被所有的牛认为是受欢迎的。
Sample Input
3 3
1 2
2 1
2 3
1 2
2 1
2 3
Sample Output
1
【数据范围】
10%的数据N<=20, M<=50
30%的数据N<=1000,M<=20000
70%的数据N<=5000,M<=50000
100%的数据N<=10000,M<=50000
【数据范围】
10%的数据N<=20, M<=50
30%的数据N<=1000,M<=20000
70%的数据N<=5000,M<=50000
100%的数据N<=10000,M<=50000
HINT
Source
博客地址:www.cnblogs.com/iwtwiioi 本文为博主原创文章,未经博主允许不得转载。一经发现,必将追究法律责任。