Each of Bessie’s NN (2≤N≤1052≤N≤105) bovine buddies (conveniently labeled 1…N1…N) owns her own farm. For each 1≤i≤N1≤i≤N, buddy ii wants to visit buddy aiai (ai≠iai≠i).
Given a permutation (p1,p2,…,pN)(p1,p2,…,pN) of 1…N1…N, the visits occur as follows.
For each ii from 11 up to NN:
Compute the maximum possible number of moos after all visits, over all possible permutations pp.
The first line contains NN.For each 1≤i≤N1≤i≤N, the i+1i+1-st line contains two space-separated integers aiai and vivi.
A single integer denoting the answer.Note that the large size of integers involved in this problem may require the use of 64-bit integer data types (e.g., a "long long" in C/C++).
4 2 10 3 20 4 30 1 40
90
If p=(1,4,3,2)p=(1,4,3,2) then
This gives a total of 10+30=4010+30=40 moos.
On the other hand, if p=(2,3,4,1)p=(2,3,4,1) then
This gives 20+30+40=9020+30+40=90 total moos. It can be shown that this is the maximum possible amount after all visits, over all permutations pp.
Problem credits: Benjamin Qi and Michael Cao
[/hide]
(Analysis by Benjamin Qi)
Observe that the edges i→aii→ai induce a directed graph where every vertex has out-degree 1. This is known as a functional graph. We can solve the problem for each connected component of the graph independently, so for the remainder of the analysis, we will assume the graph consists of a single connected component.
Call cow ii inactive if it contributes 00 to the collective pleasure value rather than vivi. From the sample case, among those cows on a simple cycle, it is easy to see that at least one of the cows must be inactive. Consider the cow cc in the cycle that occurs latest in pp. Then either acac either has not departed her farm already (in which case acac is inactive) or she has (in which case cc is inactive).
As a connected component in a functional graph always contains exactly one simple cycle, the answer must be at most the sum of all vivi minus the minimum vivi among that cycle. Furthermore, we can always construct pp that achieves this bound. The construction is as follows:
In the code below, for each connected component I use Floyd's algorithm to detect a vertex along the cycle. After that, I mark every vertex in the connected component as visited. As each connected component is processed in time proportional to its size, the runtime is O(N)O(N).
#include <bits/stdc++.h> using namespace std; template <class T> using V = vector<T>; #define all(x) begin(x), end(x) vector<int> a, v; vector<vector<int>> child; vector<bool> done; void mark_as_done(int x) { if (done[x]) return; done[x] = true; for (int c : child[x]) mark_as_done(c); } int solve(int start) { int x = start, y = start; do { x = a[x], y = a[a[y]]; } while (x != y); int min_along_cycle = INT_MAX; do { min_along_cycle = min(min_along_cycle, v[x]); x = a[x]; } while (x != y); mark_as_done(x); return min_along_cycle; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; a.resize(N + 1); v.resize(N + 1); child.resize(N + 1); int64_t ans = 0; for (int i = 1; i <= N; ++i) { cin >> a[i] >> v[i]; ans += v[i]; child[a[i]].push_back(i); } done.resize(N + 1); for (int i = 1; i <= N; ++i) if (!done[i]) ans -= solve(i); cout << ans << "\n"; }
Alternatively, if you are familiar with Gold topics, the answer is just the weight of a maximum spanning forest of the graph (treating the edges as undirected), which can be computed with Kruskal's algorithm.
#include <bits/stdc++.h> using namespace std; struct DSU { vector<int> e; void init(int N) { e = vector<int>(N, -1); } int get(int x) { return e[x] < 0 ? x : e[x] = get(e[x]); } bool unite(int x, int y) { x = get(x), y = get(y); if (x == y) return 0; if (e[x] > e[y]) swap(x, y); e[x] += e[y]; e[y] = x; return 1; } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; vector<tuple<int, int, int>> edges; for (int i = 1; i <= N; ++i) { int a, v; cin >> a >> v; edges.push_back({v, i, a}); } sort(edges.rbegin(), edges.rend()); DSU D; D.init(N + 1); int64_t ans = 0; for (auto [v, x, y] : edges) if (D.unite(x, y)) ans += v; cout << ans << "\n"; }
Bonus: Solve the problem when the vivi can be negative.
[/hide]
翰林课程体验,退费流程快速投诉邮箱: yuxi@linstitute.net 沪ICP备2023009024号-1