AmazingCounters.com

POJ 2553 The Bottom of a Graph 【scc tarjan】

图论之强连通复习开始- -

题目大意:给你一个有向图,要你求出这样的点集:从这个点出发能到达的点,一定能回到这个点

思路:强连通分量里的显然都可以互相到达 那就一起考虑,缩点后如果一个点有出边,一定不在点集内,因为缩点后是DAG,无环,因此一定不能回到原来的点,所以找到出度为0的点即可

#include<cstdio>

#include<string.h>

#include<math.h>

#include<algorithm>

#include<iostream>

#include<queue>

#define maxn 90000

#define inf 0x3f3f3f3f

using namespace std;

int head[maxn],next[maxn],point[maxn],now=0;

int dfn[maxn],low[maxn],time,col,stack[maxn];

int top,belong[maxn],out[maxn];

bool instack[maxn];

void add(int x,int y)

{

    next[++now]=head[x];

    head[x]=now;

    point[now]=y;

}

void tarjan(int k)

{

    int u;

    dfn[k]=low[k]=++time;

    instack[k]=1;

    stack[++top]=k;

    for(int i=head[k];i;i=next[i])

    {

        u=point[i];

        if(dfn[u]==0)

        {

            tarjan(u);

            low[k]=min(low[u],low[k]);

        }

        else if(instack[u])low[k]=min(low[k],low[u]);

    }

    if(low[k]==dfn[k])

    {

        ++col;

        do

        {

            u=stack[top--];

            instack[u]=0;

            belong[u]=col;

        }while(u!=k);

    }

 

}

int main()

{

    int n,m,x,y;

    while(1)

    {

        scanf("%d",&n);

        if(n==0)break;

        scanf("%d",&m);

        now=0;memset(head,0,sizeof(head));

        top=0;memset(instack,0,sizeof(instack));

        memset(out,0,sizeof(out));

        memset(dfn,0,sizeof(dfn));

        for(int i=1;i<=m;i++)

        {

            scanf("%d%d",&x,&y);

            add(x,y);

        }

        for(int i=1;i<=n;i++)if(dfn[i]==0)tarjan(i);

        for(int i=1;i<=n;i++)

        {

            for(int j=head[i];j;j=next[j])

            {

                int u=point[j];

                if(belong[i]!=belong[u])out[belong[i]]++;

            }

        }

        int flag=1;

        for(int i=1;i<=n;i++)

        {

            if(flag && out[belong[i]]==0)

            {

                printf("%d",i);

                flag^=flag;

            }

            else if(out[belong[i]]==0)printf(" %d",i);

        }

        printf("\n");

    }

    return 0;

}

posted @ 2014-12-02 23:20  philippica  阅读(212)  评论(0编辑  收藏  举报