受欢迎的奶牛(tarjan)
P2341 [USACO03FALL / HAOI2006] 受欢迎的牛 G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- tarjan算法求出各个强连通分量,缩点过程
- 在完成缩点后的图中记录每个缩点的出度,出度为0的就是答案对应的缩点,该缩点中点的个数就是答案
- 出度为0的缩点如果不止一个,那么很明显这两个点之间是不能相互到达的,那么这种情况答案就是0
#include <bits/stdc++.h>
using namespace std;
#define INF 2e9
#define MAX 100000
#define ri register int
// https://www.luogu.com.cn/problem/P2341
int head[MAX], idx;
struct Node
{
int from, to, nex;
} edge[MAX * 10];
inline void add(int u, int v)
{
edge[++idx].to = v;
edge[idx].from = u;
edge[idx].nex = head[u];
head[u] = idx;
}
int dfn[MAX], low[MAX], tim, cnt, belong[MAX], nums[MAX], top;
bool vis[MAX];
int s[MAX];
void tarjan(int now)
{
dfn[now] = low[now] = ++tim;
vis[now] = true;
s[++top] = now;
for (int i = head[now]; i; i = edge[i].nex)
{
int to = edge[i].to;
if (!dfn[to])
{
tarjan(to);
low[now] = min(low[now], low[to]);
}
else if (vis[to])
{
low[now] = min(low[now], dfn[to]);
}
}
if (dfn[now] == low[now])
{
belong[now] = ++cnt;
nums[cnt]++;
vis[now] = false;
while (s[top] != now)
{
vis[s[top]] = false;
belong[s[top]] = cnt;
nums[cnt]++;
top--;
}
top--;
}
}
int n, m, dutt[MAX];
inline void in(int &read)
{
int x = 0, f = 1;
char ch;
for (ch = getchar(); (ch < '0' || ch > '9') && ch != '-'; ch = getchar())
;
if (ch == '-')
{
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar();
}
read = x * f; //可以处理负数的读入优化
}
inline void input()
{
in(n);
in(m);
int a, b;
for (ri i = 1; i <= m; i++)
{
in(a), in(b);
add(a, b);
}
}
int main()
{
input();
for (ri i = 1; i <= n; i++)
{
if (!dfn[i])
tarjan(i);
}
for (int i = 1; i <= m; i++)
{
if (belong[edge[i].from] != belong[edge[i].to])
{
dutt[belong[edge[i].from]]++;
}
}
int ans = 0;
for (ri i = 1; i <= cnt; i++)
{
if (!dutt[i])
{
if (ans)
{
printf("0");
return 0;
}
ans = i;
}
}
printf("%d", nums[ans]);
}