1. 程式人生 > >洛谷P2341&&BZOJ1051 受歡迎的牛

洛谷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; }