Submission #1246953

#TimeUsernameProblemLanguageResultExecution timeMemory
1246953TurkhuuSwapping Cities (APIO20_swap)C++20
100 / 100
272 ms78472 KiB
#include "swap.h"
#include <bits/stdc++.h>
#define FOR(i, a, b) for (auto i = (a); i <= (b); i++)
#define ROF(i, a, b) for (auto i = (a); i >= (b); i--)
using namespace std;
int N, M, lgNM, timer;
vector<int> edge_cnt, node_cnt, l, r, p, w, lvl, deg3;
vector<vector<int>> par, ch;
int find(int x) {return p[x] == x ? x : p[x] = find(p[x]);}
void dfs(int x) {
    (x < N ? node_cnt : edge_cnt)[x]++;
    for (int i = 0; i < lgNM && par[x][i] != -1; i++)
        par[x][i + 1] = par[par[x][i]][i];
    l[x] = timer;
    if (x < N) timer++;
    for (int y : ch[x]) {
        par[y][0] = x;
        lvl[y] = lvl[x] + 1;
        dfs(y);
        deg3[x] |= deg3[y];
        node_cnt[x] += node_cnt[y];
        edge_cnt[x] += edge_cnt[y];
    }
    r[x] = timer;
}
int lca(int x, int y) {
    if (lvl[x] < lvl[y]) swap(x, y);
    FOR(i, 0, lgNM) if ((lvl[x] - lvl[y]) >> i & 1) x = par[x][i];
    if (x == y) return x;
    ROF(i, lgNM, 0) if (par[x][i] != par[y][i]) x = par[x][i], y = par[y][i];
    return par[x][0];
}
void init(int _N, int _M, std::vector<int> U, std::vector<int> V, std::vector<int> W) {
    N = _N, M = _M; lgNM = __lg(N + M);
    l.resize(N + M);
    r.resize(N + M);
    w.resize(N + M);
    p.resize(N + M); iota(p.begin(), p.end(), 0);
    ch.resize(N + M);
    lvl.resize(N + M);
    deg3.resize(N + M);
    edge_cnt.resize(N + M);
    node_cnt.resize(N + M);
    par.resize(N + M, vector<int>(lgNM + 1, -1));
    vector<int> ord(M), deg(N);
    iota(ord.begin(), ord.end(), 0);
    sort(ord.begin(), ord.end(), [&](int i, int j) {return W[i] < W[j];});
    FOR(oi, 0, M - 1) {
        int i = ord[oi], x = U[i], y = V[i];
        if (++deg[x] >= 3 || ++deg[y] >= 3) deg3[N + oi] = 1;
        x = find(x), y = find(y);
        ch[N + oi].push_back(x);
        if (x != y) ch[N + oi].push_back(y);
        p[x] = p[y] = N + oi, w[N + oi] = W[i];
    }
    dfs(N + M - 1);
}
bool check(int x) {
    return edge_cnt[x] >= node_cnt[x] || deg3[x];
}
int getMinimumFuelCapacity(int X, int Y) {
    if (!check(N + M - 1)) return -1;
    int Z = lca(X, Y);
    if (check(Z)) return w[Z];
    ROF(i, lgNM, 0) if (par[Z][i] != -1 && !check(par[Z][i])) Z = par[Z][i];
    return w[par[Z][0]];
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...