• 强连通分量+缩点(poj2553)


    http://poj.org/problem?id=2553

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

    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 inG 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 vv 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

    求出连通块里的点满足下面条件:所有能到达点v的点w,v也能到达所有的w,因此要求的是联通块,然后缩点,求出度为零的连通块里的点,然后按照升序输出元素;

    程序:

    #include"stdio.h"
    #include"string.h"
    #include"queue"
    #include"stack"
    #include"iostream"
    #define M 5009
    #define inf 100000000
    using namespace std;
    struct node
    {
        int v;
        node(int vv)
        {
            v=vv;
        }
    };
    vector<node>edge[M];
    stack<int>q;
    int use[M],low[M],dfn[M],belong[M],num,index,in[M],out[M];
    void tarjan(int u)
    {
        dfn[u]=low[u]=++index;
        q.push(u);
        use[u]=1;
        for(int i=0;i<(int)edge[u].size();i++)
        {
            int v=edge[u][i].v;
            if(!dfn[v])
            {
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(use[v])
            {
                low[u]=min(low[u],dfn[v]);
            }
        }
        if(dfn[u]==low[u])
        {
            num++;
            int p;
            do
            {
                p=q.top();
                q.pop();
                use[p]=0;
                belong[p]=num;
            }while(p!=u);
        }
    }
    void slove(int n)
    {
        num=index=0;
        memset(use,0,sizeof(use));
        memset(dfn,0,sizeof(dfn));
        for(int i=1;i<=n;i++)
            if(!dfn[i])
            tarjan(i);
    }
    int main()
    {
        int n,m,i;
        while(scanf("%d",&n),n)
        {
            scanf("%d",&m);
            for(i=1;i<=n;i++)
                edge[i].clear();
            for(i=1;i<=m;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                edge[u].push_back(node(v));
            }
            slove(n);
            if(num==1)
            {
                for(i=1;i<=n;i++)
                {
                    if(i==1)
                        printf("%d",i);
                    else
                        printf(" %d",i);
                }
                printf("
    ");
                continue;
            }
            memset(in,0,sizeof(in));
            memset(out,0,sizeof(out));
            for(int u=1;u<=n;u++)
            {
                for(int j=0;j<(int)edge[u].size();j++)
                {
                    int v=edge[u][j].v;
                    if(belong[u]!=belong[v])
                    {
                        out[belong[u]]++;
                        in[belong[v]]++;
                    }
                }
            }
            int ff=0;
            for(i=1;i<=n;i++)
            {
                if(!out[belong[i]])
                {
                    if(ff==0)
                        printf("%d",i);
                    else
                        printf(" %d",i);
                    ff++;
                }
            }
            printf("
    ");
        }
    }
    




  • 相关阅读:
    Qt:QT右键菜单
    Ubuntu 12.04安装字体
    在ubuntu下关闭笔记本触摸板
    SSL与TLS的区别以及介绍
    隔行扫描与逐行扫描的区别
    Linux下的绘图(流程图、UML、mindmap)工具
    RedHat Linux 下安装MPlayer 编译源代码方式
    循环数组实现队列的四种方式
    Linux内核spin_lock与spin_lock_irq分析
    Oracle 创建同义词
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348177.html
Copyright © 2020-2023  润新知