zoukankan      html  css  js  c++  java
  • POJ2553:The Bottom of a Graph(tarjan缩点) java程序员

    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 

  • 相关阅读:
    hdu 3333 树状数组+离线处理
    poj 2352 树状数组 OR Treap
    hdu 1698 线段树
    【概率dp】D. Card Collector
    【分段哈希】H. Paint the Wall
    【置换】G. Poker 2.0
    【概率dp】C. Race to 1 Again
    【dp】D. Caesar's Legions
    【并查集】F.find the most comfortable road
    【算法系列学习】连续邮资问题
  • 原文地址:https://www.cnblogs.com/java20130725/p/3215893.html
Copyright © 2011-2022 走看看