BZOJ1051|HAOI2006受欢迎的牛|强连通分量
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
Sample Output
1【数据范围】
10%的数据N<=20, M<=50
30%的数据N<=1000,M<=20000
70%的数据N<=5000,M<=50000
100%的数据N<=10000,M<=50000
分析:tarjan强连通分量求缩点重构图,出度为0的点若只有一个则输出其代表强连通分量的大小,否则无解。因为显然若有两个出度为0的点,两点之间不能相互欢迎。模板题。
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std; int n,m; int tot=0,cnt=0,top=0; struct node{ int to,next; }e[50001],d[50001]; int head[10001]; int dfn[10001],low[10001],q[10001]; int scc=0,h[10001],belong[10001],hav[10001];//scc是强连通分量的个数 bool vis[10001],inq[10001]; int ans=0; void dfs(int a) { int now; inq[a]=vis[a]=1; low[a]=dfn[a]=++cnt; q[++top]=a; int c=head[a]; while(c) { if (!vis[e[c].to]) { dfs(e[c].to); low[a]=min(low[a],low[e[c].to]); } else if (inq[e[c].to]) low[a]=min(low[a],dfn[e[c].to]); c=e[c].next; } if (low[a]==dfn[a]) { scc++; while (now!=a) { now=q[top--]; inq[now]=0; belong[now]=scc; ++hav[scc]; } } } void rebuild() { cnt=0; for (int i=1; i<=n; i++) { int c=head[i]; while (c) { if (belong[e[c].to]!=belong[i]) { d[++cnt].to=belong[e[c].to]; d[cnt].next=h[i]; h[i]=cnt; } c=d[c].next; } } } void work() { for (int i=1; i<=scc; i++) if (!h[i]) { if (ans) { ans=0; return; } else ans=hav[i]; if (i==1) cout << hav[i]<< endl; } } void tarjan() { for (int i=1; i<=n; i++) if (!vis[i]) dfs(i); rebuild(); } int main() { cin >> n >> m; for (int i=1; i<=m; i++) { int x,y,z; cin >> x >> y; e[++tot].to=y; e[tot].next=head[x]; head[x]=tot; } tarjan(); work(); cout << ans; system("pause"); return 0; }