有向图强联通分量+缩点SCC~

View Code
1 #include <cstdio>
2 #include <cstring>
3
4  #define MIN(a,b) (a < b ? a : b)
5
6  const int N = 5005;
7 const int M = 100005;
8
9 struct List
10 {
11 int v;
12 List *next;
13 } pool[M], *c[N], *g[N], *pp;
14
15 inline void add_edge(int u, int v, List *c[])
16 {
17 pp->v = v;
18 pp->next = c[u];
19 c[u] = pp++;
20 }
21
22 int n, m, label, tot, top;
23 int low[N], dfn[N], num[N], stack[N], hash[N], all_cnt[N], all_n[N], queue[N];
24 bool used[N];
25 bool mark[N];
26
27 void SCC_VISIT(int u)
28 {
29 low[u] = dfn[u] = label++;
30 stack[++top] = u;
31
32 for (List *p = c[u]; p; p = p->next)
33 {
34 int v = p->v;
35 if (used[v]) continue;
36 if (dfn[v] == 0) SCC_VISIT(v), low[u] = MIN(low[u],low[v]);
37 else low[u] = MIN(low[u],dfn[v]);
38 }
39
40 if (low[u] == dfn[u])
41 {
42 ++tot;
43 do
44 {
45 num[stack[top]] = tot;
46 used[stack[top]] = true;
47 }
48 while ( stack[top--] != u );
49 }
50 }
51
52 int bfs(int s)
53 {
54 int qh = -1;
55 int qe = 0;
56 int ret = all_cnt[s];
57
58 memset(used,false,sizeof(used));
59
60 queue[0] = s;
61 used[s] = true;
62
63 while (qh != qe)
64 {
65 int u = queue[++qh];
66 for (List * p = g[u];p;p = p->next)
67 if (!used[p->v])
68 {
69 queue[++qe] = p->v;
70 used[p->v] = true;
71 ret += all_cnt[p->v];
72 }
73 }
74
75 return ret - 1;
76 }
77
78 void SCC(int cas)
79 {
80 int i;
81
82 label = 1;
83 top = -1;
84 tot = 0;
85 for (i = 1; i <= n; ++i) all_n[i] = 0, all_cnt[i] = 0, dfn[i] = 0, mark[i] = false, used[i] = false;
86 for (i = 1; i <= n; ++i)
87 if (dfn[i] == 0) SCC_VISIT(i);
88
89 for (i = 1; i <= n; ++i) hash[i] = -1;
90 for (i = 1; i <= tot; ++i) g[i] = NULL;
91 for (i = 1; i <= n; ++i)
92 {
93 int u = num[i];
94 for (List *p = c[i]; p; p = p->next)
95 {
96 int v = num[p->v];
97 if (u != v && hash[v] != u) hash[v] = u, add_edge(u, v, g);
98 }
99 }
100
101 for (int i = 1;i <= n;i++)
102 all_cnt[num[i]]++;
103
104 int max_n = 0;
105 for (int i = 1;i <= tot;i++)
106 {
107 all_n[i] = bfs(i);
108 if (max_n < all_n[i])
109 max_n = all_n[i];
110 }
111
112 for (int i = 1;i <= tot;i++)
113 if (all_n[i] == max_n)
114 mark[i] = true;
115
116 printf("Case %d: %d\n",cas,max_n);
117 max_n = -1;
118 for (int i = 1;i <= n;i++)
119 if (mark[num[i]])
120 {
121 if (max_n != -1) printf(" ");
122 printf("%d",i-1);
123 max_n = 0;
124 }
125 printf("\n");
126 }
127
128 int main()
129 {
130 int cas;
131 int i, j;
132
133 scanf("%d",&cas);
134
135 for (int cc = 1;cc <= cas;cc++)
136 {
137 scanf("%d %d", &n, &m);
138 for (i = 1; i <= n; ++i) c[i] = NULL;
139 pp = pool;
140
141 while ( m-- )
142 {
143 scanf("%d %d", &i, &j);
144 add_edge(j + 1, i + 1, c);
145 }
146
147 SCC(cc);
148 }
149 return 0;
150 }