链接:https://vjudge.net/problem/HDU-3639
题意:
有n个小朋友在一个班级中,现在要选择班长。收集了小朋友们的意见,一条意见表示为A认为B合适。这个是具备传递性的,A认为B合适,B认为C合适。那么A也会认为C合适。
现在需要提供一份候选人名单,这里面的人,是被最多的人,认为合适的。
思路:
tarjan,缩点,再根据缩点之后的点建立反向的新图,用来求每个人的的票数。
不过在找得票数的时候用记忆化搜索wa了,不知道为啥
代码:
#include <iostream> #include <memory.h> #include <string> #include <istream> #include <sstream> #include <vector> #include <stack> #include <algorithm> #include <map> #include <queue> #include <math.h> #include <cstdio> #include <set> #include <iterator> #include <cstring> using namespace std; typedef long long LL; const int MAXN = 5e3+10; const int INF = 0x3f3f3f3f; vector<int> G[MAXN]; vector<int> Gr[MAXN]; stack<int> St; int Dfn[MAXN], Low[MAXN]; int Vis[MAXN], Dis[MAXN]; int Fa[MAXN], Fans[MAXN]; int Num[MAXN]; int n, m; int times, cnt; void Init() { for (int i = 1;i <= n;i++) G[i].clear(), Fa[i] = i, Gr[i].clear(); memset(Dfn, 0, sizeof(Dfn)); memset(Low, 0, sizeof(Low)); memset(Vis, 0, sizeof(Vis)); memset(Dis, 0, sizeof(Dis)); memset(Num, 0, sizeof(Num)); memset(Fans, -1, sizeof(Fans)); times = cnt = 0; } void Tarjan(int x) { Dfn[x] = Low[x] = ++times; Vis[x] = 1; St.push(x); for (int i = 0;i < G[x].size();i++) { int node = G[x][i]; if (Dfn[node] == 0) { Tarjan(node); Low[x] = min(Low[x], Low[node]); } else if (Vis[node] == 1) Low[x] = min(Low[x], Dfn[node]); } if (Low[x] == Dfn[x]) { cnt++; Num[cnt] = 0; while (St.top() != x) { Num[cnt]++; Fa[St.top()] = cnt; Vis[St.top()] = 0; St.pop(); } Num[cnt]++; Fa[St.top()] = cnt; Vis[St.top()] = 0; St.pop(); } } int GetFans(int x) { Vis[x] = 1; int sum = 0; for (int i = 0;i < Gr[x].size();i++) { int node = Gr[x][i]; if (Vis[node] == 1) continue; sum += Num[node] + GetFans(node); } return sum; } int main() { int t, cn = 0; cin >> t; while (t--) { cin >> n >> m; Init(); // cin >> Cost[i]; int l, r; for (int i = 1;i <= m;i++) { scanf("%d%d", &l, &r); l++, r++; // cin >> l >> r; G[l].push_back(r); } for (int i = 1;i <= n;++i) if (!Dfn[i]) Tarjan(i); for (int i = 1;i <= n;i++) { for (int j = 0;j < G[i].size();j++) { int node = G[i][j]; int l = Fa[i], r = Fa[node]; if (l != r) { ++Dis[l]; Gr[r].push_back(l); } } } int number = -1, is = 0; for (int i = 1;i <= cnt;i++) { if (Dis[i] == 0) { memset(Vis, 0, sizeof(Vis)); Fans[i] = Num[i]-1 + GetFans(i); number = max(number, Fans[i]); } } cout << "Case " << ++cn << ": " << number << endl; for (int i = 1;i <= n;i++) { if (Fans[Fa[i]] == number) { if (is++ == 0) cout << i-1; else cout << ' ' << i-1 ; } } cout << endl; } return 0; }