刚看到此题, 感觉很简单,就顺着感觉写了。 后来,写不下去啦, 整不清楚了, 网上看了一下, 要建反图,
思路: 先建图, 后缩点,后根据缩后的点, 二次建图,但要建反图, 记录个缩点出度, 找出度为0 的, 进行一次dfs,
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
const int M = 50005;
struct node {
int to;
int next;
}num[M*2], num1[M];
int ins[M];
int head1[M];
int nod[M];
int belong[M];
int dfn[M];
int low[M];
int rdu[M];
int sccf[M];
int head[M];
int sum[M];
int vist[M];
stack<int>s;
int index, cont;
int ans;
int T, n, m, e, e1;
void init() {
e = 0;
index = 1;
cont = 0;
e1 = 0;
memset(num, 0, sizeof(num));
memset(head, -1, sizeof(head));
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(sccf, 0, sizeof(sccf));
memset(rdu, 0, sizeof(rdu));
memset(sum, 0, sizeof(sum));
memset(head1, -1, sizeof(head1));
memset(nod, 0, sizeof(nod));
memset(belong, 0, sizeof(belong));
}
void add(int a, int b) {
num[e].to = b;
num[e].next = head[a];
head[a] = e++;
}
void add1(int a, int b) { //建反图,
num1[e1].to = b;
num1[e1].next = head1[a];
head1[a] = e1++;
}
void Tanjian(int u) { //缩点,
int v;
dfn[u] = low[u] = index++;
ins[u] = 1;
s.push(u);
for(int k = head[u]; k != -1; k = num[k].next) {
v = num[k].to;
if(!dfn[v]) {
Tanjian(v);
low[u] = min(low[u], low[v]);
}
else if(ins[v]) {
low[u] = min(low[u], low[v]);
}
}
if(low[u] == dfn[u]) {
cont++;
do {
v = s.top();
s.pop();
sccf[v] = cont;
belong[cont]++; //存储没给缩点所包函的节点数,
ins[v] = 0;
}while(u != v);
}
}
void dfs(int u, int p) {
int v;
for(int k = head1[u]; k != -1; k = num1[k].next) {
v = num1[k].to;
if(vist[v] != p) {
nod[p] += belong[v];
vist[v] = p; //记录v点是否遍历过,
dfs(v, p);
}
}
}
void getdu() {
for(int i = 0; i < n; i++) {
for(int k = head[i]; k != -1; k = num[k].next) {
int v = num[k].to;
if(sccf[i] != sccf[v]) { //建反图
add1(sccf[v], sccf[i]);
rdu[sccf[i]]++; //存储出度,
}
}
}
ans = 0;
for(int i = 1; i <= cont; i++) {
memset(vist, 0, sizeof(vist));
if(rdu[i] == 0) {
vist[i] = i;
nod[i] = belong[i] -1;
dfs(i, i);
ans = max(ans, nod[i]);
}
}
}
int main()
{
int a, b, q = 1;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
init();
for(int i = 0; i < m; i++) {
scanf("%d%d", &a, &b);
if(a == b)
continue;
add(a, b);
}
for(int i = 0; i < n; i++) {
if(!dfn[i]) {
Tanjian(i);
}
}
getdu();
int flag = 0;
printf("Case %d: %d\n", q++, ans);
for(int i = 0; i < n; i++) {
if(nod[sccf[i]] == ans) {
if(!flag) {
printf("%d", i);
flag = 1;
}
else
printf(" %d", i);
}
}
printf("\n");
}
return 0;
}