题目:http://poj.org/problem?id=2553
题意:一张有向图G,G图中从v可达的所有点w,也都可以达到v,这样的v称为sink。按照大小全部输出,没有输出空行。
方法:tarjan
View Code
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define Max(A,B) ((A)>(B)?(A):(B))
#define Min(A,B) ((A)<(B)?(A):(B))
#define clr(a,b) memset(a, b, sizeof(a))
using namespace std;
const int MAXV = 10000+10;
const int inf = 0x3f3f3f3f;
const int N = 10010;
const int M = 50010;
int e, ev[M], nxt[M], head[N];
bool instack[N];
int dfn[N], low[N], dindex, q[N], ed;
int belong[N], bcnt;
int n, m;
bool out[N];
int ans[N];
int initout[N];
void addedge(int u, int v)
{
ev[e] = v; nxt[e] = head[u]; head[u] = e++;
}
void tarjan(int u)
{
int i, v;
dfn[u] = low[u] = ++dindex;
instack[u] = 1;
q[ed++] = u;
for (i = head[u]; ~i; i = nxt[i])
{
v = ev[i];
if (!dfn[v])
{
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (instack[v])
{
low[u] = min(low[u], dfn[v]);
}
}
if (dfn[u] == low[u])
{
do{
belong[v = q[--ed]] = bcnt;
instack[v] = 0;
}while (v != u);
bcnt++;
}
}
void solve()
{
ed = bcnt = dindex = 0;
clr(dfn, 0); clr(instack, 0);
for (int i=0; i<n; i++)
if (!dfn[i]) tarjan(i);
}
int main()
{
//freopen("D:/a.txt", "r", stdin);
while (~scanf("%d", &n) && n)
{
e = 0;
clr(head, -1);
clr(initout, 0);
scanf("%d", &m);
for (int i=0; i<m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
addedge(u-1, v-1);
initout[u-1]++;
}
solve();
clr(out, 0);
for (int i=0; i<n; i++)
{
for (int j=head[i]; ~j; j=nxt[j])
{
if (belong[i] != belong[ev[j]])
{
out[belong[i]] = true;
}
}
}
int t = 0;
for (int i=0; i<n; i++)
{
if (initout[i]==0) {ans[t++] = i+1; continue;}
if (!out[belong[i]]) ans[t++] = i+1;
}
printf("%d", ans[0]);
for (int i=1; i<t; i++) {
printf(" %d", ans[i]);
}
puts("");
}
}