题目
题目描述
每一头牛的愿望就是变成一头最受欢迎的牛。现在有 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;
}
0 条评论