[HAOI2006]受欢迎的牛

1051: [HAOI2006]受欢迎的牛Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 7267 Solved: 3868
[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

solution

不是一道很难的题,很容易看出来的是这个题首先就要Tarjan缩点,关键在于缩完点之后要怎么办,可以发现的是,如果这个图中有两个及以上出度为0的强连通分量,那么这个图里面就一定没有受欢迎的奶牛。那么直接记录图里出度为0的强连通分量是否多于一个就可以了。个数可以在跑Tarjan的时候记录。一开始Tarjan写错了居然找了半个小时

Code

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#define re register
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define MAXN 1000007
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(arr) memset(arr, 0, sizeof(arr))
const int inf = 0x3f3f3f3f;
struct po
{
    int nxt,to;
};
po edge[MAXN];
int n,m,dfn[MAXN],low[MAXN],col[MAXN],stack[MAXN],vis[MAXN],tot[MAXN];
int head[MAXN],num,color_num,s,tp,cnt,cd[MAXN],flag,ans;
inline int read()
{
    int x=0,c=1;
    char ch=' ';
    while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
    while(ch=='-') c*=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
    return x*c;
}
inline void add_edge(int from,int to)
{
    edge[++num].nxt=head[from];
    edge[num].to=to;
    head[from]=num;
}
inline void Tarjan(int u)
{
    dfn[u]=++cnt;
    low[u]=cnt;
    vis[u]=1;
    stack[++tp]=u;
    for(re int i=head[u];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(!dfn[v]){
            Tarjan(v);
            low[u]=min(low[v],low[u]);
        } else if(vis[v]) low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u]){
        color_num++;
        col[u]=color_num;
        tot[color_num]++;
        vis[u]=0;
        while(stack[tp]!=u){
            col[stack[tp]]=color_num;
            tot[color_num]++;
            vis[stack[tp--]]=0;
        }
        tp--;
    }
}

int main() 
{
    //freopen("date.in","r",stdin);
    n=read();m=read();
    for(re int i=1;i<=m;i++){
    	int x=read(),y=read();
    	add_edge(x,y);
    }
    for(re int i=1;i<=n;i++)
    	if(!dfn[i]) Tarjan(i);
    for(re int i=1;i<=n;i++){
    	for(re int j=head[i];j;j=edge[j].nxt){
    		int v=edge[j].to;
    		if(col[v]!=col[i]) cd[col[i]]++;
    	}
    }
    for(re int i=1;i<=color_num;i++){
    	if(cd[i]==0) ans=i,flag++;
    	if(flag>1){
    		cout<<"0";
    		return 0;
    	}
    }
    cout<<tot[ans];
    return 0;
}
posted @ 2018-04-24 18:26  ~victorique~  阅读(135)  评论(0编辑  收藏  举报
Live2D