POJ 2553 The Bottom of a Graph (Trajan 强连通分量 缩点)
题目描述很吓人。。。题意就是求出强连通分量,然后缩点得到DAG, 求DAG中出度为0的缩点,并输出缩点包含的集合(可能有多个这样的缩点)
渣代码:
View Code
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <stack>
5 #include <algorithm>
6
7 using namespace std;
8
9 const int N = 5010;
10 const int M = 51000;
11
12 struct node {
13 int to;
14 int next;
15 } g[M];
16
17 int head[N], blong[N];
18 int dfn[N], low[N];
19 int out[N];
20 int t, ind, cnt;
21 bool vis[N], flag[N];
22
23 stack<int> s;
24
25 void init() {
26 memset(head, 0, sizeof(head));
27 memset(blong, 0, sizeof(blong));
28 memset(dfn, 0, sizeof(dfn));
29 memset(low, 0, sizeof(low));
30 memset(vis, 0, sizeof(vis));
31 memset(out, 0, sizeof(out));
32 t = 1; ind = cnt = 0;
33 }
34
35 void add(int u, int v) {
36 g[t].to = v; g[t].next = head[u]; head[u] = t++;
37 }
38
39 void tarjan(int u) {
40 int v, i;
41 vis[u] = true;
42 s.push(u);
43 low[u] = dfn[u] = ++ind;
44 for(i = head[u]; i; i = g[i].next) {
45 v = g[i].to;
46 if(!dfn[v]) {
47 tarjan(v);
48 low[u] = min(low[u], low[v]);
49 } else if(vis[v]) {
50 low[u] = min(dfn[v], low[u]);
51 }
52 }
53 if(low[u] == dfn[u]) {
54 cnt++;
55 do {
56 v = s.top(); s.pop();
57 blong[v] = cnt;
58 vis[v] = false;
59 } while(v != u);
60 }
61 }
62
63 int main() {
64 //freopen("data.in", "r", stdin);
65
66 int n, m, f;
67 int a, b, i, j;
68 while(scanf("%d", &n), n) {
69 scanf("%d", &m);
70 init();
71 for(i = 1; i <= m; i++) {
72 scanf("%d%d", &a, &b);
73 add(a, b);
74 }
75 for(i = 1; i <= n; i++) {
76 if(!dfn[i]) tarjan(i);
77 }
78
79 for(i = 1; i <= n; i++) {
80 for(j = head[i]; j; j = g[j].next) {
81 a = g[j].to;
82 if(blong[i] != blong[a])
83 out[blong[i]]++;
84 }
85 }
86 memset(flag, false, sizeof(flag));
87
88 for(b = 1; b <= cnt; b++) {
89 if(!out[b]) flag[b] = true;
90 }
91
92 for(f = 0, i = 1; i <= n; i++) {
93 if(flag[blong[i]]) {
94 if(f == 0) {printf("%d", i); f = 1;}
95 else printf(" %d", i);
96 }
97 }
98 printf("\n");
99 }
100 return 0;
101 }