好題。
在有向圖中找到強連通子圖,縮點,記上裏面有幾頭牛,變成DAG。
然後找出出度爲0的點。如果這樣的點的數量不等於1顯然輸出0。否則答案就是這個點的原點數。
爲了方便,反向建邊,變統計出度爲入度。枚舉每一個原圖的點u,如果找到原圖中與u點相連的v不屬於同一個scc,那麼入度+1。(即不重建圖。
打了四遍這個題真TM爽
#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 10001
#define maxm 50001
using namespace std;
int head[maxn];
struct edge{
int to, nxt;
}e[maxm];
int n, m, tot, top, cnt, col;
int dfn[maxn], st[maxn], low[maxn], scc[maxn];
int sl[maxn], ind[maxn];
void add(int u, int v){
e[++tot].nxt=head[u];
e[tot].to=v;
head[u]=tot;
}
void tarjan(int u){
dfn[u]=low[u]=++cnt;
st[++top]=u;
for(int i=head[u]; i; i=e[i].nxt){
int v=e[i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u], low[v]);
}else if(!scc[v])
low[u]=min(low[u], dfn[v]);
}
if(low[u]==dfn[u]){
scc[u]=++col;
++sl[col];
while(st[top]!=u){
++sl[col];
scc[st[top]]=col;
top--;
}
top--;
}
}
int main(){
scanf("%d%d", &n, &m);
int x, y;
for(int i=1; i<=m; i++){
scanf("%d%d", &x, &y);
add(y,x);
}
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(scc[i]!=scc[v])
ind[scc[v]]++;
}
int ans=0, indtj=0;
for(int i=1; i<=col; i++)
if(!ind[i])
ans=sl[i], indtj++;
if(indtj==1)
printf("%d", ans);
else printf("0");
return 0;
}