POJ-2553 The Bottom of a Graph (强连通分量[Tarjan])

The Bottom of a Graph
http://poj.org/problem?id=2553
Time Limit: 3000MS   Memory Limit: 65536K
     

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  Gand 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. POJ-2553 The Bottom of a Graph (强连通分量[Tarjan])_第1张图片

Sample Input

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

Sample Output

1 3
2

题目大意:给定一个有向图,求所有的点v(对于任一点w,若v可达w,则w可达v)?

注意理解题意即可(只有理解了,才能看懂样例...)

满足题意的v点有两种情况:

①对于任一点w,v可达w,且w可达v,即v、w互相可达,满足该情况的点在同一个强连通分量中(且该强连通分量不与其他点连通)

②对于任一点w,v均不可达w,满足该情况的点是出度为0的点

所以可以先求出所有的强连通分量,并缩点,则只剩下情况②,则所有出度为0的缩点都满足题意,即缩点中的点都满足题意

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;

const int MAXN=5005;

int n,m,num,cnt,top,tot;
int stak[MAXN],ans[MAXN];
int low[MAXN],dfn[MAXN],color[MAXN],outdeg[MAXN];//biocks[i]表示删掉i点后,能形成的连通块数
vector<int> g[MAXN];
bool isIn[MAXN];

void Tarjan(int u) {
    stak[++top]=u;
    isIn[u]=true;
    dfn[u]=low[u]=++num;
    int v;
    for(int i=0;i<g[u].size();++i) {
        v=g[u][i];
        if(dfn[v]==0) {
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(isIn[v]&&dfn[v]<low[u])
            low[u]=dfn[v];
    }

    if(dfn[u]==low[u]) {
        ++cnt;
        do {
            v=stak[top--];
            isIn[v]=false;
            color[v]=cnt;//缩点
        } while(v!=u);
    }
}


int main() {
    int s,e;
    while(scanf("%d",&n),n!=0) {
        scanf("%d",&m);
        for(int i=1;i<=n;++i) {
            g[i].clear();
            dfn[i]=outdeg[i]=0;
            isIn[i]=false;
        }
        while(m-->0) {
            scanf("%d%d",&s,&e);
            g[s].push_back(e);
        }

        tot=cnt=num=top=0;
        for(int i=1;i<=n;++i) {
            if(dfn[i]==0)
                Tarjan(i);
        }
        for(int i=1;i<=n;++i) {
            for(int j=0;j<g[i].size();++j) {
                if(color[i]!=color[g[i][j]])
                    ++outdeg[color[i]];//统计各缩点的出度
            }
        }
        for(int i=1;i<=cnt;++i) {
            if(outdeg[i]==0) {//若出度为0
                for(int j=1;j<=n;++j) {
                    if(color[j]==i)//若点j缩成点i
                        ans[tot++]=j;
                }
            }
        }
        sort(ans,ans+tot);
        if(tot>0) {//本题不会出现无解情况,DAG中必有出度为0的点,否则有环
            printf("%d",ans[0]);
            for(int i=1;i<tot;++i)
                printf(" %d",ans[i]);
        }
        printf("\n");
    }
    return 0;
}


你可能感兴趣的:(poj,图论,Tarjan,连通分量)