P2341 [USACO03FALL / HAOI2006] 受欢迎的牛 G —— Tarjan缩点
[USACO03FALL / HAOI2006] 受欢迎的牛 G
题目背景
本题测试数据已修复。
题目描述
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果 \(A\) 喜欢 \(B\),\(B\) 喜欢 \(C\),那么 \(A\) 也喜欢 \(C\)。牛栏里共有 \(N\) 头奶牛,给定一些奶牛之间的爱慕关系,请你算出有多少头奶牛可以当明星。
输入格式
第一行:两个用空格分开的整数:\(N\) 和 \(M\)。
接下来 \(M\) 行:每行两个用空格分开的整数:\(A\) 和 \(B\),表示 \(A\) 喜欢 \(B\)。
输出格式
一行单独一个整数,表示明星奶牛的数量。
样例 #1
样例输入 #1
3 3
1 2
2 1
2 3
样例输出 #1
1
提示
只有 \(3\) 号奶牛可以做明星。
【数据范围】
对于 \(10\%\) 的数据,\(N\le20\),\(M\le50\)。
对于 \(30\%\) 的数据,\(N\le10^3\),\(M\le2\times 10^4\)。
对于 \(70\%\) 的数据,\(N\le5\times 10^3\),\(M\le5\times 10^4\)。
对于 \(100\%\) 的数据,\(1\le N\le10^4\),\(1\le M\le5\times 10^4\)。
分析
先跑Tarjan求出所有SCC。
当新图上有且仅有一个出度为零的点 $ id $ 时有 $ ans=siz[id] $ 。
#include<bits/stdc++.h>
using namespace std;
const int N=2e4+100,M=1e5+100;
int n,m;
int dfn[N],low[N],tot,dd;
int sta[N],top,id,scc[N],siz[N];
int deg1[N],deg2[N];
bool inc[N];
vector<int>g[N],h[N];
void go(int u)
{
sta[++top]=u;
inc[u]=1;
low[u]=dfn[u]=++tot;
for(int i=0;i<deg1[u];++i)
{
int v=g[u][i];
if(!dfn[v])
{
go(v);
low[u]=min(low[u],low[v]);
}
else if(inc[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
++id;
while(sta[top]!=u)
{
scc[sta[top]]=id;
++siz[id];
inc[sta[top]]=0;
--top;
}
scc[u]=id;
++siz[id];
inc[u]=0;
--top;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1,x,y;i<=m;++i)
{
scanf("%d%d",&x,&y);
g[x].push_back(y);
++deg1[x];
}
for(int i=1;i<=n;++i)
if(!dfn[i])
go(i);
for(int i=1;i<=n;++i)
{
for(int j=0;j<deg1[i];++j)
{
int v=g[i][j];
if(scc[v]!=scc[i])
h[scc[i]].push_back(scc[v]);
}
}
for(int i=1;i<=id;++i)
deg2[i]=unique(h[i].begin(),h[i].end())-h[i].begin();
int tot=0,num=0;
for(int i=1;i<=id;++i)
{
if(deg2[i]==0)
{
++tot;
num=siz[i];
}
}
if(tot!=1){cout<<0;}
else cout<<num;
return 0;
}
本文来自博客园,作者:Glowingfire,转载请注明原文链接:https://www.cnblogs.com/Glowingfire/p/18576247