/*
poj2186 强连通分量缩点
Author : lcy
Time : 2017-10-1
*菜鸡的第一道强连通分量题
牛A对牛B存在喜欢关系,并且这种关系具备传递性。给出所有喜欢关系,问有多少只牛被所有牛喜欢。
参考:http://blog.csdn.net/mengxiang000000/article/details/51613914
跑一遍tarjan,将每个强连通分量缩成一个点
可以保证缩点后是DAG即有向无环图
对于DAG,当且仅当图中存在1点出度为0时有答案,答案值为该点所在强连通分量中的点的个数。

强连通分量的作用:将图缩点转化为DAG,简化模型。
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
using namespace std;
#define ll long long 
#define fr(i,a,b) for(int i=a;i<=b;i++)
#define frr(i,a,b) for(int i=a;i>=b;i--)
#define ms(a,b) memset(a,b,sizeof(a))
#define scfd(a) scanf("%d",a)
#define scflf(a) scanf("%lf",a)
#define scfs(a) scanf("%s",a)
#define ptfd(a) printf("%d\n",a)
#define ptfs(a) printf("%s\n",a)
#define showd(a,b) printf(a"=%d\n",b)
#define showlf(a,b) printf(a"=%lf\n",b)
#define shows(a,b) printf(a"=%s\n",b)
#define mmcp(a,b) memcpy(a,b,sizeof(b))
#define pb(a) push_back(a)
// #define DEBUG
using namespace std;
const int MAXN=10005;
int fa[MAXN],dfn[MAXN],low[MAXN],tot;
bool inq[MAXN],v[MAXN];
vector<int>g[MAXN];
stack<int>q;
void add_edge(int a,int b){
    g[a].pb(b);
}
void tarjan(int x){
    int sz=g[x].size();
    low[x]=dfn[x]=++tot;
    inq[x]=true;q.push(x);
    fr(i,0,sz-1){
        int t=g[x][i];
        if(v[t])
           continue; 
        else if(inq[t])
            low[x]=min(low[x],dfn[t]);
        else{
            tarjan(t);
            low[x]=min(low[x],low[t]);
        }
    }
    if(dfn[x]==low[x]){
        int t;
        do{
            t=q.top(),q.pop();
            v[t]=true,inq[t]=false,fa[t]=x;
        }
        while(t!=x);
    }
}
int n,m;
void init(){
    ms(v,false);
    ms(inq,false);
}
void solve(){
    fr(i,1,n)
        if(!dfn[i])
            tarjan(i);
    int ansfa;
    int cntzro=0;
    int out[MAXN];
    fr(i,0,MAXN-1)out[i]=-1;
    fr(i,1,n){
        if(out[fa[i]]>0)
            continue;
        if(out[fa[i]]==-1)
            out[fa[i]]=0;
        int sz=g[i].size();
        fr(j,0,sz-1)
            if(fa[g[i][j]]!=fa[i]){
                out[fa[i]]++;
                break;
            }
    }   
    fr(i,0,n)
        if(!out[i]){
            cntzro++;
            ansfa=i;
        }
    if(!cntzro||cntzro>1)
        printf("0\n"); 
    else{
        int ans=0;
        fr(i,1,n)
            if(fa[i]==ansfa)
                ans++;
        printf("%d\n",ans);
    }
}
int main(){
    init();
    scanf("%d%d",&n,&m);
    fr(i,1,m){
        int a,b;
        scanf("%d%d",&a,&b);
        add_edge(a,b);
    }
    solve();
    #ifdef DEBUG
    fr(i,1,n)
        printf("%d ",fa[i]);
    #endif
    return 0;
}
 posted on 2017-10-01 16:25  cylcy  阅读(130)  评论(0)    收藏  举报