1. 程式人生 > >BZOJ(3) 1051: [HAOI2006]受歡迎的牛

BZOJ(3) 1051: [HAOI2006]受歡迎的牛

algo 模板 sum clu bzoj back -s iostream --

1051: [HAOI2006]受歡迎的牛

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 7365 Solved: 3937
[Submit][Status][Discuss]

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

HINT

100%的數據N<=10000,M<=50000 思路:tarjin模板。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 50010
using namespace std;
int n,m,tim,tot,top,sumcol; int col[MAXN],sum[MAXN],num[MAXN]; int to[MAXN],net[MAXN],from[MAXN],head[MAXN]; int vis[MAXN],low[MAXN],dfn[MAXN],strack[MAXN],visstrack[MAXN]; void add(int u,int v){ to[++tot]=v;from[tot]=u;net[tot]=head[u];head[u]=tot; } void tarjin(int now){ strack[++top]=now; low[now]
=dfn[now]=++tim; vis[now]=1;visstrack[now]=1; for(int i=head[now];i;i=net[i]) if(visstrack[to[i]]) low[now]=min(low[now],dfn[to[i]]); else if(!vis[to[i]]){ tarjin(to[i]); low[now]=min(low[now],low[to[i]]); } if(low[now]==dfn[now]){ sumcol++;sum[sumcol]++; col[now]=sumcol; while(strack[top]!=now){ col[strack[top]]=sumcol; visstrack[strack[top]]=0; top--;sum[sumcol]++; } visstrack[now]=0; top--; } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v); } for(int i=1;i<=n;i++) if(!vis[i]) tarjin(i); for(int i=1;i<=tot;i++) if(col[from[i]]!=col[to[i]]) num[col[from[i]]]++; int flag=0,ans; for(int i=1;i<=sumcol;i++) if(num[i]==0){ flag++; ans=i; } if(flag!=1) printf("0\n"); else printf("%d\n",sum[ans]); }

BZOJ(3) 1051: [HAOI2006]受歡迎的牛