【图论】The Bottom of a Graph

[POJ2553]The Bottom of a Graph
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 11182   Accepted: 4608

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

 
题目大意:输出有哪些点在有向图中满足它能到达的点都可以到它
试题分析:缩点后输出出度为0的强联通分量中的点即可。
 
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;

inline int read(){
	int x=0,f=1;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
	for(;isdigit(c);c=getchar()) x=x*10+c-'0';
	return x*f;
}
const int MAXN=5101;
const int INF=999999;
int N,M;
vector<int> vec[MAXN];
bool inq[MAXN];
int que[MAXN];
int dfn[MAXN],low[MAXN];
int tar[MAXN];
bool oud[MAXN];
int tot,Col,tmp;

void Tarjan(int x){
	tot++;
	dfn[x]=low[x]=tot;
	que[++tmp]=x;
	inq[x]=true;
	for(int i=0;i<vec[x].size();i++){
		int to=vec[x][i];
		if(!dfn[to]){
			Tarjan(to);
			low[x]=min(low[x],low[to]);
		}
		else if(inq[to]) low[x]=min(low[x],dfn[to]);
	}
	if(dfn[x]==low[x]){
		++Col; tar[x]=Col;
		inq[x]=false;
		while(x!=que[tmp]){
			int k=que[tmp];
			tar[k]=Col;
			inq[k]=false;
			tmp--;
		}
		tmp--;
	}
	return ;
}
vector<int> vec2[MAXN];
int ans[MAXN];
int ans2[MAXN];
int atmp,atmp2;
int main(){
	while(1){
		N=read(); if(!N) break;
		M=read();
		memset(inq,false,sizeof(inq));
		memset(oud,false,sizeof(oud));
		atmp=atmp2=0;
		memset(dfn,0,sizeof(dfn));
		tmp=0,Col=0,tot=0;
		memset(tar,0,sizeof(tar));
		for(int i=1;i<=N;i++) vec[i].clear(),vec2[i].clear();
		for(int i=1;i<=M;i++){
			int u=read(),v=read();
			vec[u].push_back(v);
		}
		for(int i=1;i<=N;i++) if(!dfn[i]) Tarjan(i);
		for(int i=1;i<=N;i++){
			//size[tar[i]]++;
			vec2[tar[i]].push_back(i);
			for(int j=0;j<vec[i].size();j++){
				if(tar[i]!=tar[vec[i][j]])
					oud[tar[i]]=true;
			}
		}
		for(int i=1;i<=Col;i++){
			if(!oud[i]) ans[++atmp]=i;
		}
		for(int i=1;i<=atmp;i++){
			for(int j=0;j<vec2[ans[i]].size();j++){
				ans2[++atmp2]=vec2[ans[i]][j];
			}
		}
		sort(ans2+1,ans2+atmp2+1);
		for(int i=1;i<atmp2;i++) printf("%d ",ans2[i]);
		printf("%d\n",ans2[atmp2]);
	}
}
posted @ 2017-08-04 10:46  wxjor  阅读(256)  评论(0编辑  收藏  举报