poj2553

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

冥冥之中觉得见过这个题.也就只是见过…
这题就是求缩点后出读为0的强联通分量,并且陈组成这个强联通分量里的点输出出来.
代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <stack>
#include <cstring>
#define mem(a,b) memset(a,b,sizeof(a))
#define maxn int(1e6+100)
using namespace std;
stack<int>st;
int cnt, k, m, n, cntt;
int dfn[maxn], low[maxn], head[maxn], vis[maxn], id[maxn], out[maxn], ans[maxn];
struct node {
	int v, next, w;
} edge[maxn];
void addedge(int u, int v) {
	edge[++cntt].v = v;
	edge[cntt].next = head[u];
	head[u] = cntt;
}
void tarjan(int u) {
	dfn[u] = low[u] = ++k;
	st.push(u);
	vis[u] = 1;
	for (int i = head[u]; i; i = edge[i].next) {
		int v = edge[i].v;
		if (!dfn[v]) {
			tarjan(v);
			low[u] = min(low[u], low[v]);
		} else if (vis[u]) {
			low[u] = min(low[u], dfn[v]);
		}
	}
	if (low[u] == dfn[u]) {
		cnt++; int v;
		do {
			v = st.top();
			st.pop();
			vis[v] = 0;
			id[v] = cnt;
		} while (u != v);
	}
}
int main() {
	int x, y;
	while (scanf("%d", &n) != EOF && n) {
		memset(head, 0, sizeof head); cntt = cnt = k = 0;
		memset(low, 0, sizeof low);
		memset(dfn, 0, sizeof dfn);
		memset(ans, 0, sizeof ans);
		memset(id, 0, sizeof id);
		memset(out, 0, sizeof out);
		memset(vis, 0, sizeof vis);
		scanf("%d", &m); int tot = 0;
		for (int i = 0; i < m; i++) {
			scanf("%d%d", &x, &y);
			addedge(x, y);
		}
		for (int i = 1; i <= n; i++) {
			if (!dfn[i]) {
				tarjan(i);
			}
		}
		for (int i = 1; i <= n; i++) {
			for (int j = head[i]; j; j = edge[j].next) {
				int u = i, v = edge[j].v;
				if (id[u] != id[v]) {
					out[id[u]]++;
				}
			}
		}
		for (int i = 1; i <= cnt; i++) {
			if (out[i] > 0) continue;
			for (int j = 1; j <= n; j++)
				if (id[j] == i)
					ans[++tot] = j;
		}
		sort(ans + 1, ans + tot + 1);
		for (int i = 1; i <= tot; i++)
			if (i == tot) cout << ans[i] << endl;
			else cout << ans[i] << " ";
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值