LOJ Chen 2509. Arrangement of "AHOI / HNOI2018" (thinking set)

Keywords: C++

meaning of the title

Title Link

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
*/

Posted by vamosbenedikt on Sun, 08 Dec 2019 01:27:41 -0800