POJ-tarjan-强连通分量+缩点-Popular Cows

来源:互联网 发布:mac os系统下载百度云 编辑:程序博客网 时间:2024/04/30 01:13

这个是我写的 kosaraju算法。(双搜索)
http://blog.csdn.net/qq_35781950/article/details/70859526

这个主意要缩点,不是真正的缩点。而是把一个强连通分量的的点存在的出度 都给写在一个 数组上,相当于缩点处理了。(tarjan的那个num数组就是为了缩点而生的,不是么)

#include <iostream>#include <cstdio>#include <cstdlib>#include <stack>#include <vector>#include <cstring>using namespace std;const int maxn=50005;int dfn[maxn];//dfs顺序。和一种求lca的序不一样??int low[maxn];//最小能够到达的点。int index1;//记录时间的标号bool state[maxn];//是否在栈里.stack<int>s;vector<int>G[maxn];int cnt[maxn];int num[maxn];int scc;int du[maxn];void tarjan(int u){  dfn[u]=low[u]=++index1;   s.push(u);   state[u]=true;   for(int i=0;i<G[u].size();i++){       if(!dfn[G[u][i]]){          tarjan(G[u][i]);          low[u]=min(low[G[u][i]],low[u]);       }       else if(state[G[u][i]])         low[u]=min(low[u],dfn[G[u][i]]);//在次遇见你。。   }   if(low[u]==dfn[u])    {        scc++;        for(;;)        {            int x = s.top();s.pop();            cnt[x]=scc;            num[scc]++;            if(x==u)break;        }    }}void init(){     memset(cnt,0,sizeof(cnt));     memset(low,0,sizeof(low));     memset(num,0,sizeof(num));     memset(dfn,0,sizeof(dfn));     memset(du,0,sizeof(du));     scc=0;}int main(){   int m,n;    int a,b;    scanf("%d%d",&m,&n);    init();    for(int i=1;i<=n;i++){        scanf("%d%d",&a,&b);        G[a].push_back(b);    }    for(int i=1;i<=m;i++){        if(!dfn[i]){            tarjan(i);        }    }    //缩点。    for(int i=1;i<=m;i++){        a=cnt[i];        for(int j=0;j<G[i].size();j++){            b=cnt[G[i][j]];            if(a!=b){                du[a]++;//有出度            }        }    }    int tim=0;    int f=0;    for(int i=1;i<=scc;i++){        if(du[i]==0){            tim++;            f=i;        }    }    if(f>1)        printf("0\n");    else    {   int sum=0;        for(int i=1;i<=m;i++){          if(cnt[i]==f)            sum++;       }        printf("%d\n",sum);    }    return 0;}
阅读全文
0 0
原创粉丝点击