题目
样例
这道题就是先缩点,然后反向dfs到入度为0的点就好了,只要dfs到一个新节点,该点所代表的分量节点数就都加到sum上去,表示新加了很多粉丝.最后找最大粉丝值的分量点输出即可.
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <string.h>
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define _for1(i,a,b) for( int i=(a); i<(b); ++i)
#define _for2(i,a,b) for( int i=(a); i>(b); i--)
#define _rep1(i,a,b) for( int i=(a); i<=(b); ++i)
#define _rep2(i,a,b) for( int i=(a); i>=(b); i--)
typedef long long ll;
using namespace std;
#define max1 30005
#define maxn 5005
vector<int> G[max1], G2[max1];//G是正向,G2是反向
stack<int> S;
int n, m;
int dfn[maxn], low[maxn],sccno[maxn];
int scccnt, tclock;
int num[maxn], ind[maxn], fan[maxn];
bool vis[maxn];
void tarjan(int u) {
dfn[u] = low[u] = ++tclock;
S.push(u);
_for1(i, 0, G[u].size()) {
int v = G[u][i];
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (!sccno[v])
low[u] = min(low[u], low[v]);
}
if (low[u] == dfn[u]) {
scccnt++;
num[scccnt] = 0;
while (1) {
int v = S.top();
S.pop();
sccno[v] = scccnt;
num[scccnt]++;
if (v == u)
break;
}
}
}
int dfs(int u) {
vis[u] = true;
int sum = 0;
_for1(i, 0, G2[u].size()) {
int v = G2[u][i];
if (!vis[v])
sum += num[v] + dfs(v);
}
return sum;
}
int main() {
int T;
cin >> T;
_rep1(kase, 1, T) {
while (!S.empty())
S.pop();
cin >> n >> m;
_for1(i, 0, n)
G[i].clear();
while (m--) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
}
mem(dfn, 0), mem(low, 0), mem(sccno, 0), mem(num, 0), mem(ind, 0), mem(fan, 0);
scccnt = tclock = 0;
_for1(i, 0, n)
if (!dfn[i])
tarjan(i);
/*_for1(i, 0, n)
cout << sccno[i] << " ";
cout << endl;*/
_rep1(i, 1, scccnt)
G2[i].clear();
_for1(u, 0, n)
_for1(i, 0, G[u].size()) {
int v = G[u][i];
int x = sccno[u], y = sccno[v];
if (x != y) {
ind[x]++;
G2[y].push_back(x);
}
}
int maxfan = -1;
_rep1(i, 1, scccnt) {
if (!ind[i]) {
mem(vis, 0);
int sum = num[i] - 1 + dfs(i);
fan[i] = max(fan[i], sum);
}
maxfan = max(fan[i], maxfan);
}
bool win[maxn];
mem(win, 0);
_for1(i, 0, n)
if (fan[sccno[i]] == maxfan)
win[i] = true;
cout << "Case " << kase << ":" << " " << maxfan << endl;
int flag = 1;
_for1(i, 0, n)
if (win[i]) {
printf("%d ", i);
}
cout << " ";
}
return 0;
}