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

 

posted @ 2018-10-20 18:53  kenlig  阅读(...)  评论(... 编辑 收藏