POJ2553:The Bottom of a Graph(tarjan缩点)

The Bottom of a Graph
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 7005   Accepted: 2871

Description

We will use the following (standard) definitions from graph theory. Let V be a nonempty and finite set, its elements being called vertices (or nodes). Let E be a subset of the Cartesian product V×V, its elements being called edges. Then G=(V,E) is called a directed graph. 
Let n be a positive integer, and let p=(e1,...,en) be a sequence of length n of edges ei∈E such that ei=(vi,vi+1) for a sequence of vertices (v1,...,vn+1). Then p is called a path from vertex v1 to vertex vn+1 in G and we say that vn+1 is reachable from v1, writing (v1→vn+1). 
Here are some new definitions. A node v in a graph G=(V,E) is called a sink, if for every node w in G that is reachable from v, v is also reachable from w. The bottom of a graph is the subset of all nodes that are sinks, i.e.,bottom(G)={v∈V|∀w∈V:(v→w)⇒(w→v)}. You have to calculate the bottom of certain graphs.

Input

The input contains several test cases, each of which corresponds to a directed graph G. Each test case starts with an integer number v, denoting the number of vertices of G=(V,E), where the vertices will be identified by the integer numbers in the set V={1,...,v}. You may assume that 1<=v<=5000. That is followed by a non-negative integer e and, thereafter, e pairs of vertex identifiers v1,w1,...,ve,we with the meaning that (vi,wi)∈E. There are no edges other than specified by these pairs. The last test case is followed by a zero.

Output

For each test case output the bottom of the specified graph on a single line. To this end, print the numbers of all nodes that are sinks in sorted order separated by a single space character. If the bottom is empty, print an empty line.

Sample Input

3 3
1 3 2 3 3 1
2 1
1 2
0

Sample Output

1 3
2

Source

MYCode:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAX 5010
struct node
{
    int v;
    int next;
}E[MAX*MAX];
int head[MAX];
int num;
int dfn[MAX];
int st[MAX];
bool instack[MAX];
int low[MAX];
int id[MAX];
int top;
int ct;
int tot;
int n,m;
int in[MAX];
int out[MAX];
int ans[MAX];
void init()
{
    memset(dfn,0,sizeof(dfn));
    memset(head,-1,sizeof(head));
    memset(instack,0,sizeof(instack));
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    num=0;
    ct=0;
    top=0;
    tot=0;
}
void add(int s,int t)
{
    E[num].v=t;
    E[num].next=head[s];
    head[s]=num++;
}
void dfs(int cur)
{
    //cout<<"vis "<<cur<<endl;
    dfn[cur]=low[cur]=++ct;
    st[top++]=cur;
    instack[cur]=1;
    int i;
    for(i=head[cur];i!=-1;i=E[i].next)
    {
        int v=E[i].v;
        if(!dfn[v])
        {
            dfs(v);
            if(low[v]<low[cur])
            low[cur]=low[v];
        }
        else if(instack[v] && dfn[v]<low[cur])
        low[cur]=dfn[v];
    }
    if(dfn[cur]==low[cur])
    {
        tot++;
        //cout<<"tot="<<tot<<endl;
        for(;st[top]!=cur;)
        {
            int j=st[--top];
            id[j]=tot;
            instack[j]=false;
        }
    }
}
void tarjan()
{
    int i;
    for(i=1;i<=n;i++)
    {
        if(!dfn[i])
        {
            dfs(i);
        }
    }
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)
        break;
        scanf("%d",&m);
        int i,j;
        int s,t;
        init();
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&s,&t);
            add(s,t);
            //add(t,s);
        }
        tarjan();
        for(i=1;i<=n;i++)
        {
            int id1=id[i];
            for(j=head[i];j!=-1;j=E[j].next)
            {
                int id2=id[E[j].v];
                if(id1==id2)
                continue;
                out[id1]++;
                in[id2]++;
            }
        }
        int cnt=0;
        for(i=1;i<=n;i++)
        {
            if(out[id[i]]==0)
            {
                ans[cnt++]=i;
            }
        }
        for(i=0;i<cnt;i++)
        {
            printf("%d",ans[i]);
            if(i!=cnt-1)
            printf(" ");
        }
        printf("\n");
    }
}

//

tarjan()缩点,所有出度为零的强连通分支里的顶点构成the bottom of graph 

posted @ 2012-11-24 15:30  java程序员-c  阅读(131)  评论(0编辑  收藏  举报