poj 2553 The Bottom of a Graph

xiaoxiao2021-02-27  333

The Bottom of a Graph Time Limit: 3000MS Memory Limit: 65536KTotal Submissions: 10912 Accepted: 4497

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

Ulm Local 2003 题目大意:如果v点能够到的点,反过来能够到达v点,则称这个点为sink点,输出所有的sink点 解题思路:求连通分量,然后出度为0的连通分量里面的点就是sink点 AC代码: #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <stack> using namespace std; #define MAX 100005 #define MAXN 500005 struct Edge { int u; int v; int next; } edge[MAXN]; int DFN[MAX], low[MAX], in[MAX], out[MAX]; int flag[MAX], step[MAX], head[MAX]; int sum[MAX]; stack<int>S; int res, tot, M, ans, ans1, N; void Init() { memset(DFN, 0, sizeof(DFN)); memset(low, 0, sizeof(low)); memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); memset(flag, 0, sizeof(flag)); memset(head, -1, sizeof(head)); memset(sum, 0, sizeof(sum)); memset(edge, 0, sizeof(edge)); memset(step, 0, sizeof(step)); if(!S.empty()) S.pop(); tot = 0, res = 0; } void addedge(int u, int v, int k) { edge[k].u = u, edge[k].v = v, edge[k].next = head[u], head[u] = k; } void tarjan(int u) { DFN[u] = low[u] = ++tot; flag[u] = 1; S.push(u); for(int j = head[u]; j != -1; j = edge[j].next) ///更新low值 { int v = edge[j].v; if(!DFN[v]) { tarjan(v); low[u] = min(low[u],low[v]); } else if(flag[v]) { low[u] = min(low[u],low[v]); } } int v; if(DFN[u]==low[u]) ///缩点 { do { v = S.top(); S.pop(); step[v] = res; sum[res]++; flag[v] = 0; } while(u!=v); res++; } } void solve() { for(int i=0; i<N; i++) for(int j=head[i]; j!=-1; j=edge[j].next) ///统计缩点后的各点的出度 { if(step[i]!=step[edge[j].v]) out[step[i]]++; } int f, yy=0; for(int i = 0; i < N; i++) { if(!out[step[i]]) flag[i] = 1; } for(int i = 0; i < N; i++) { if(flag[i]) printf("%d ",i + 1); } printf("\n"); } int main() { while(~scanf("%d",&N)&&N) { scanf("%d",&M); Init(); for(int i = 0; i < M; i++) { int a, b; scanf("%d%d",&a,&b); addedge(a-1,b-1,i); ///建图 } for(int i = 0; i < N; i++) { if(!DFN[i]) { tarjan(i); } } solve(); } return 0; }
转载请注明原文地址: https://www.6miu.com/read-1667.html

最新回复(0)