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

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]);
    
}

 

posted @ 2018-06-03 07:46  一蓑烟雨任生平  阅读(137)  评论(0编辑  收藏  举报