受欢迎的奶牛-洛谷2341
(可能是寒假集训时就留的题吧,结果被我咕到了现在...
tarjan的简单应用,这还是很简单看出来。
那么明星奶牛是 图中唯一一个出度为0的强联通分量。
如果存在两个或者两个以上的出度为0的强联通分量,则不存在明星奶牛,因为这几个出度为0的强连通分量之间无法传递“爱慕”
所以,最终答案就是强联通分量中的奶牛个数!
#include<cstdio>
#include<algorithm>
#include<queue>
#include<stack>
#define ll long long
using namespace std;
inline ll read()
{
ll sum = 0, p = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-')
p = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
(sum *= 10) += ch - '0';
ch = getchar();
}
return sum * p;
}
const int maxn = 10005,maxm = 50005;
struct edge
{
int nxt,to;
}e[maxm];
int n,m,cnt,tot,ncnt;
int dfn[maxn],low[maxn],mrk[maxn],id[maxn],du[maxn],head[maxn];
bool vis[maxn];
stack<int> q;
void add(int a,int b)
{
e[++cnt].to = b;
e[cnt].nxt = head[a];
head[a] = cnt;
}
void tarjan(int x)
{
dfn[x] = low[x] = ++tot;
q.push(x);
vis[x] = true;
for(int i = head[x];i;i = e[i].nxt)
{
int v = e[i].to;
if(!dfn[v])
{
tarjan(v);
low[x] = min(low[x],low[v]);
}
else if(vis[v])
low[x] = min(low[x],dfn[v]);
}
int k;
if(dfn[x] == low[x])
{
ncnt++;
do
{
k = q.top();
q.pop();
vis[k] = false;
id[k] = ncnt;
mrk[ncnt]++;
}while(x != k);
}
}
int main()
{
n = read(),m = read();
for(int i = 1;i <= m;i++)
{
int a = read(),b = read();
add(a,b);
}
for(int i = 1;i <= n;i++)
if(!dfn[i])
tarjan(i);
for(int i = 1;i <= n;i++)
for(int j = head[i];j;j = e[j].nxt)
{
int v = e[j].to;
if(id[i] != id[v])
du[id[i]]++;
}
int ans = 0;
for(int i = 1;i <= ncnt;i++)
if(!du[i])
{
if(ans)
{
printf("0\n");
return 0;
}
ans = i;
}
printf("%d\n",mrk[ans]);
return 0;
}