meaning of the title
Sol
Fairy question Orz
First of all, it's not hard to see that if we connect an edge from \ (a \) to \ (i \), we will get a tree with \ (0 \) as the root (because each point must have an entry, and the presence of a ring indicates that there is no solution). At the same time, we need to ensure that the father node must appear before the child node when arranging
Next consider direct greed. For some points with small weight, we need to make them appear as early as possible, and at the same time meet the conditions of selection.
Then we can start from the small point, merge with his father in turn, and delete the point (that is, if the father is deleted, the point will be deleted immediately)
The following content is copied from Here
And then we can use set directly
Complexity: \ (O(n\log n) \)
#include<bits/stdc++.h> #define LL long long using namespace std; const int MAXN = 5e5 + 10, SS = 1e7 + 10; template<typename A, typename B> inline void chmax(A &x, B y) { x = x > y ? x : y; } inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N, a[MAXN], fa[MAXN], vis[MAXN], ufa[MAXN]; LL w[MAXN], siz[MAXN]; vector<int> v[MAXN]; struct comp { bool operator ()(int x, int y) { return w[x] * siz[y] == w[y] * siz[x] ? x < y : w[x] * siz[y] < w[y] * siz[x]; } }; int find(int x) { return ufa[x] == x ? ufa[x] : ufa[x] = find(ufa[x]); } set<int, comp> s; int dfs(int x) { vis[x] = 1; for(auto &to : v[x]) { if(vis[to] == 1) return 1; if(dfs(to)) return 1; } vis[x] = 2; return 0; } int main() { N = read(); for(int i = 1; i <= N; i++) { fa[i] = read(); v[fa[i]].push_back(i); } for(int i = 1; i <= N; i++) if(!vis[i]) if(dfs(i)) {puts("-1"); return 0;} for(int i = 1; i <= N; i++) w[i] = read(), ufa[i] = i, siz[i] = 1, s.insert(i); siz[0] = 1; ufa[0] = 0; LL ans = 0; for(int i = 1; i <= N; i++) { int x = *s.begin(); s.erase(s.begin()); int f = find(fa[find(x)]); if(f) s.erase(f); ans += siz[f] * w[x]; siz[f] += siz[x]; w[f] += w[x]; ufa[x] = f; if(f) s.insert(f); } cout << ans; return 0; } /* 3 0 1 1 5 7 3 */