定理 有向无环图中唯一出度为0的点,一定可以由任何点出发均可达
由于无环,所以从任何点出发往前走,必然终止于一个出度为0的点
tarjan缩点后找是否有唯一出度为0的点存在
#include <iostream> #include<cstdio> #include<vector> #include<stack> #include<cstring> using namespace std; vector<int> p[50010]; stack<int> s; int color[50010],out[50010],dfn[50010],low[50010],ind,tm,n,m; bool flag[50010],vis[50010]; void tarjan(int now) { vis[now]=true; dfn[now]=low[now]=++ind; s.push(now); flag[now]=true; for (int i=0;i<(int)p[now].size();i++) { int v=p[now][i]; if (!vis[v]) { tarjan(v); low[now]=min(low[now],low[v]); } else if (flag[v]) low[now]=min(low[now],dfn[v]); } if (dfn[now]==low[now]) { int v; do { v=s.top(); s.pop(); flag[v]=false; color[v]=tm; } while(now!=v); tm++; } } int main() { freopen("in.in","r",stdin); scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); p[a].push_back(b); } memset(vis,false,sizeof(vis)); memset(flag,false,sizeof(flag)); memset(out,0,sizeof(out)); ind=0; tm=1; for (int i=1;i<=n;i++) { if (!vis[i]) tarjan(i); } for (int i=1;i<=n;i++) for (int j=0;j<(int)p[i].size();j++) { int x=p[i][j]; if (color[i]!=color[x]) out[color[i]]++; } int cans=0; tm--; for (int i=1;i<=tm;i++) { if (out[i]==0) { if (cans!=0) {cout<<0<<endl;return 0;} else cans=i; } } int ans=0; for (int i=1;i<=n;i++) if (color[i]==cans) ans++; cout<<ans<<endl; return 0; }