洛谷P2341&&BZOJ1051 受欢迎的牛
很著名的Tarjan题。
跑个Tarjan,统计下入度。没啦。
#include<iostream> #include<cstdio> #include<cmath> #include<stack> #define ll long long #define maxn 10001 using namespace std; struct Edge{ int nxt,to,dis; }edge[20*maxn]; stack<int> s; int scc_cnt,sccnum[maxn],du[maxn],cnt,dfn[maxn],low[maxn],head[20*maxn],num[maxn],num_edge,n,m; inline void addedge(int from,int to){ edge[++num_edge].nxt=head[from]; edge[num_edge].to=to; head[from]=num_edge; } void tarjan(int x){ dfn[x]=low[x]=++cnt; s.push(x); for(int i=head[x];i;i=edge[i].nxt){ int y=edge[i].to; if(!dfn[y]){ tarjan(y); low[x]=min(low[x],low[y]); } else if(!sccnum[y]){ low[x]=min(dfn[y],low[x]); } } if(low[x]==dfn[x]){ scc_cnt++; for(;;){ num[scc_cnt]++; int y=s.top(); // tot[scc_cnt]+=a[y]; s.pop(); sccnum[y]=scc_cnt; if(y==x) break; } } } int main(){ cin>>n>>m; for(int i=1;i<=m;i++){ int x,y; cin>>x>>y; addedge(x,y); } 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=edge[j].nxt){ int x=edge[j].to; if(sccnum[x]!=sccnum[i]){ du[sccnum[i]]++; } } } int ans=0; for(int i=1;i<=scc_cnt;i++){ if(!du[i]){ if(ans){ cout<<"0"; return 0; } ans=i; } } cout<<num[ans]; return 0; }