POJ 2553

来源:互联网 发布:数据分析 excel 编辑:程序博客网 时间:2024/06/05 11:43

题意:如果v点能够到的点,反过来也能够到v点,则称这个点为sink点,输出所有的sink点


思路:求下强连通分量,出度为0的连通分量里的点都是sink点


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<stack>using namespace std;const int maxn = 1e4+5;int n, m, dfn[maxn], low[maxn], belong[maxn], out[maxn];int dfs_clock, scc_cnt;bool is[maxn];vector<int> g[maxn];stack<int> s;void tarjan(int u){    dfn[u] = low[u] = ++dfs_clock;    s.push(u);    for(int i = 0; i < g[u].size(); i++)    {        int v = g[u][i];        if(!dfn[v])        {            tarjan(v);            low[u] = min(low[u], low[v]);        }        else if(!belong[v])            low[u] = min(low[u], dfn[v]);    }    if(low[u] == dfn[u])    {        scc_cnt++;        while(1)        {            int x = s.top(); s.pop();            belong[x] = scc_cnt;            if(x == u) break;        }    }}void find_scc(){    while(!s.empty()) s.pop();    dfs_clock = scc_cnt = 0;    memset(belong, 0, sizeof(belong));    memset(dfn, 0, sizeof(dfn));    for(int i = 1; i <= n; i++)        if(!dfn[i])            tarjan(i);}void solve(){    memset(out, 0, sizeof(out));    memset(is, 0, sizeof(is));    for(int u = 1; u <= n; u++)        for(int i = 0; i < g[u].size(); i++)        {            int v = g[u][i];            if(belong[u] != belong[v])                out[belong[u]]++;        }    for(int i = 1; i <= scc_cnt; i++)        if(!out[i])            is[i] = 1;    int lead = 0;    for(int i = 1; i <= n; i++)        if(is[belong[i]])        {            if(lead++) printf(" ");            printf("%d", i);        }    puts("");}int main(void){    while(cin >> n && n)    {        scanf("%d", &m);        for(int i = 0; i < maxn; i++)            g[i].clear();        for(int i = 1; i <= m; i++)        {            int u, v;            scanf("%d%d", &u, &v);            g[u].push_back(v);        }        find_scc();        solve();    }    return 0;}



The Bottom of a Graph
Time Limit: 3000MS Memory Limit: 65536KTotal Submissions: 10891 Accepted: 4491

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 31 3 2 3 3 12 11 20

Sample Output

1 32


1 0