强连通分量的tarjan算法应用(一)

来源:互联网 发布:openstreetmap数据分析 编辑:程序博客网 时间:2024/06/05 09:12

题目链接:POJ 2186

解题思路:
先用tarjan算法求出图中的强连通分量,再求出缩点后唯一的叶结点即可。

代码:

#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;int n,m,dfn[100005],low[100005],cnt;int scnt,stack[100005],scc,vis[100005],ans[100005];bool instack[100005];vector<int> vec[100005];void tarjan(int index){    int tmp;    dfn[index]=low[index]=++cnt;    instack[index]=1, stack[++scnt]=index;    for(int i=0;i<vec[index].size();i++)    {        tmp=vec[index][i];        if(!dfn[tmp])        {            tarjan(tmp);            low[index]=min(low[index],low[tmp]);        }        else if(instack[tmp])        {            low[index]=min(low[index],dfn[tmp]);        }    }    if(dfn[index]==low[index])    {        scc++;        do{            tmp=stack[scnt--];            instack[tmp]=false;            vis[tmp]=scc,ans[scc]++;        }        while(tmp!=index);    }}int main(){    while(~scanf("%d %d",&n,&m))    {        memset(vec,0,sizeof(vec));        int x,y;        while(m--)        {            scanf("%d %d",&x,&y);            vec[x].push_back(y);        }        cnt=scc=0;        memset(dfn,0,sizeof(dfn));        memset(low,0,sizeof(low));        memset(instack,0,sizeof(instack));        for(int i=1;i<=n;i++)            if(!dfn[i])                tarjan(i);        cnt=0;        memset(dfn,0,sizeof(dfn));        for(int i=1;i<=n;i++)        {            for(int j=0;j<vec[i].size();j++)            {                if(vis[i]!=vis[vec[i][j]])                    dfn[vis[i]]=1;            }        }        for(int i=1;i<=scc;i++)            if(!dfn[i])            {                cnt++;            }               if(cnt==1)        {            printf("%d\n",ans[1]);        }        else        {            printf("0\n");        }    }    return 0;}
0 0
原创粉丝点击