poj2553The Bottom of a Graph(强连通+缩点)

原创 2013年07月20日 12:42:14

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

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

Source


题目大意:给定一个有向图,求一个点集,要求这个点集里的所有点能到达的点,也都能到达这个点。

题目分析:就是求强连通嘛,不过并不是求所有的强连通。因为强连通之间也可能有边相连。将强连通缩点后就将一张有向图转化成DAG,只能将其中出度为0的强连通分量输出,因为只有这些强连通分量中的点能够相互到达。其他的强连通分量可以到达这个强连通分量,但是回不去了,所以不符合。

详情请见代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 5005;
const int M = 1000005;
struct edge
{
    int to,next;
}g[M];
int head[N];
int scc[N];
int stack1[N];
int stack2[N];
int out[N];
int vis[N];
int ans[N];
int n,m;

void init()
{
    for(int i = 1;i <= n;i ++)
    {
        head[i] = -1;
        scc[i] = out[i] = vis[i] = 0;
    }
}

void dfs(int cur,int &sig,int &ret)
{
    vis[cur] = ++ sig;
    stack1[++stack1[0]] = cur;
    stack2[++stack2[0]] = cur;
    for(int i = head[cur];i != -1;i = g[i].next)
    {
        if(vis[g[i].to] == 0)
            dfs(g[i].to,sig,ret);
        else
            if(scc[g[i].to] == 0)
            {
                while(vis[stack2[stack2[0]]] > vis[g[i].to])
                    stack2[0] --;
            }
    }
    if(stack2[stack2[0]] == cur)
    {
        ++ret;
        stack2[0] --;
        do
        {
            scc[stack1[stack1[0]]] = ret;
        }while(stack1[stack1[0] --] != cur);
    }
}

int Gabow()
{
    int i,sig,ret;
    stack1[0] = stack2[0] = sig = ret = 0;
    for(i = 1;i <= n;i ++)
        if(!vis[i])
            dfs(i,sig,ret);
    return ret;
}

void solve()
{
    int i,j,num;
    num = Gabow();
    if(num == 1)
    {
        for(i = 1;i < n;i ++)
            printf("%d ",i);
        printf("%d\n",i);
        return;
    }
    for(i = 1;i <= n;i ++)
    {
        for(j = head[i];j != -1;j = g[j].next)
        {
            if(scc[i] != scc[g[j].to])
                out[scc[i]] ++;
        }
    }
    int ansnum = 0;
    for(i = 1;i <= num;i ++)
    {
        if(out[i] == 0)
        {
            for(j = 1;j <= n;j ++)
                if(scc[j] == i)
                    ans[ansnum ++] = j;
        }
    }
    sort(ans,ans + ansnum);
    for(i = 0;i < ansnum - 1;i ++)
        printf("%d ",ans[i]);
    printf("%d\n",ans[i]);
}

int nextint()
{
    char c;
    int ret;
    while((c = getchar()) > '9' || c < '0')
        ;
    ret = c - '0';
    while((c = getchar()) >= '0' && c <= '9')
        ret = ret * 10 + c - '0';
    return ret;
}
int main()
{
    int i,j,a,b;
    while(n = nextint(),n)
    {
        m = nextint();
        init();
        for(i = 1;i <= m;i ++)
        {
            a = nextint();
            b = nextint();
            g[i].to = b;
            g[i].next = head[a];
            head[a] = i;
        }
        solve();
    }
    return 0;
}
//996K	110MS



相关文章推荐

poj2553 The Bottom of a Graph--Kosaraju算法 & 缩点 & 强连通分量

原题链接:http://poj.org/problem?id=2553 题意:n个点,m对点的关系,定义link点:一个点u所能到达的点,反过来都能到达u,那么点u就是link点。升序输出所...
  • LaoJiu_
  • LaoJiu_
  • 2016年09月10日 14:38
  • 231

POJ 2553 The Bottom of a Graph 强连通分量+缩点 tarjan or kosaraju

题目的意思是求有向图中满足“自己可达的顶点都能到达自己”的顶点个数 显然,在一个强连通分量中,每个点都符合要求,但是 如果强连通分量中有某个点跟外面的某个点相连了,这个强连通分量就不符合要求了,很显...

POJ 2553 - The Bottom of a Graph(强连通分量, 缩点)

题意:如果v点能够到的点,反过来也能够到v点,则称这个点为sink点,输出所有的sink点 思路:求下强连通分量,出度为0的连通分量里的点都是sink点 代码: #include...
  • CillyB
  • CillyB
  • 2017年04月28日 19:38
  • 125

【连通图|强连通+缩点】POJ-2553 The Bottom of a Graph

给出一个图,求出图上所有”自己可达的顶点都能回到自己“的点。

POJ 2553 The Bottom of a Graph 缩点之后求出度为0的强联通分量的元素

点击打开链接 The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: ...

POJ 2553 The Bottom of a Graph (强连通分量)

题目地址:POJ 2553 题目意思不好理解。题意是:G图中从v可达的所有点w,也都可以达到v,这样的v称为sink。然后升序输出所有的sink。 对于一个强连通分量来说,所有的点都符合这一条件,...

POJ 2553——The Bottom of a Graph(强连通分量)

The Bottom of a Graph Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 10222 ...

POJ 2553:The Bottom of a Graph【强连通】

The Bottom of a Graph Time Limit : 6000/3000ms (Java/Other)   Memory Limit : 131072/65536K (Java/O...

POJ 2553 The Bottom of a Graph(强连通分量)

POJ 2553 The Bottom of a Graph(强连通分量) http://poj.org/problem?id=2553 题意:给你一个有向图,要你输出图的bottom点.bottom...

poj2553——The Bottom of a Graph(强连通分量)

DescriptionWe will use the following (standard) definitions from graph theory. Let V be a nonempty a...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:poj2553The Bottom of a Graph(强连通+缩点)
举报原因:
原因补充:

(最多只允许输入30个字)