题目

传送门= ̄ω ̄=

题目描述

  每一头牛的愿望就是变成一头最受欢迎的牛。现在有 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

0 条评论

发表回复

Avatar placeholder

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