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

题目链接: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;
}

你可能感兴趣的:(强连通分量的tarjan算法应用(一))