题目

传送门= ̄ω ̄=

题目描述

  每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
牛被所有的牛认为是受欢迎的。

输入格式

  第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可
能出现多个A,B)

输出格式

  一个数,即有多少头牛被所有的牛认为是受欢迎的。

样例输入

3 3
1 2
2 1
2 3

样例输出

1

提示

100%的数据N<=10000,M<=50000

题目来源

没有写明来源

# 题解

强连通分量缩点模板题,H2O。

缩点后,找出度为0的强连通分量。如果有多个则说明答案为0,否则输出那一个强连通分量所含的点的个数。

代码(kosaraju算法):

#include <bits/stdc++.h>
using namespace std;
int n,m,cnt,scc[10005],out[10005],siz[10005],ans;
bool book[10005];
vector<int> g[2][10005];
stack<int> sta;
void initdfs(int u)
{
    book[u]=1;
    for(vector<int>::iterator i=g[0][u].begin();i!=g[0][u].end();i++)
        if(!book[*i])initdfs(*i);
    sta.push(u);
}
void dfs(int u)
{
    book[u]=1,scc[u]=cnt,siz[cnt]++;
    for(vector<int>::iterator i=g[1][u].begin();i!=g[1][u].end();i++)
        if(!book[*i])dfs(*i);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1,a,b;i<=m;i++)
        scanf("%d%d",&a,&b),g[0][a].push_back(b),g[1][b].push_back(a);
    for(int i=1;i<=n;i++)if(!book[i])initdfs(i);
    memset(book,0,sizeof(book));
    while(!sta.empty())
    {
        int i=sta.top();sta.pop();
        if(!book[i])cnt++,dfs(i);
    }
    for(int u=1;u<=n;u++)
        for(vector<int>::iterator i=g[0][u].begin();i!=g[0][u].end();i++)
            if(scc[u]!=scc[*i])out[scc[u]]++;
    for(int i=1;i<=cnt;i++)
        if(!out[i])
        {
            if(ans){printf("0\n");return 0;}
            else ans=i;
        }
    printf("%d\n",siz[ans]);
    return 0;
}

分享至ヾ(≧∇≦*)ゝ:
分类: 所有

XZYQvQ

炒鸡辣鸡的制杖蒟蒻一枚QvQ

发表评论

电子邮件地址不会被公开。 必填项已用*标注

你是机器人吗? =。= *