Submission #1247533

#TimeUsernameProblemLanguageResultExecution timeMemory
1247533badge881Swapping Cities (APIO20_swap)C++20
100 / 100
291 ms65388 KiB
#include "swap.h"
#include <bits/stdc++.h>

typedef long long ll;

using namespace std;

const ll INF = 1e15;

vector<vector<ll>> adj, up;
vector<ll> s, p, v2, dg, v3, v4, dist;
vector<tuple<ll, ll, ll>> edges;

ll cnt = 0, n;

ll _find(ll x)
{
    if (p[x] != x)
        p[x] = _find(p[x]);
    return p[x];
}

void _union(ll a, ll b, ll w)
{
    ll x = a, y = b;
    a = _find(a), b = _find(b);
    if (a == b)
    {
        adj[cnt].push_back(v3[a]);
        adj[v3[a]].push_back(cnt);
        dg[x]++;
        dg[y]++;
        v2[cnt] = 1;
        v4[cnt] = w;
        v3[a] = cnt++;
        return;
    }
    adj[cnt].push_back(v3[a]);
    adj[v3[a]].push_back(cnt);
    adj[cnt].push_back(v3[b]);
    adj[v3[b]].push_back(cnt);
    dg[x]++;
    dg[y]++;
    if (dg[x] >= 3 || dg[y] >= 3)
        v2[cnt] = 1;
    if (v2[v3[a]] || v2[v3[b]])
        v2[cnt] = 1;
    v4[cnt] = w;
    if (s[a] < s[b])
        swap(a, b);
    v3[a] = cnt;
    s[a] += s[b];
    p[b] = a;
    cnt++;
}

void dfs(ll node, ll parent, ll val)
{
    up[node][0] = parent;
    if (v2[node])
        val = v4[node];
    v4[node] = val;

    if (dist[parent] - dist[up[parent][1]] == dist[up[parent][1]] - dist[up[up[parent][1]][1]])
        up[node][1] = up[up[parent][1]][1];
    else
        up[node][1] = parent;

    for (ll to : adj[node])
    {
        if (to == parent)
            continue;
        dist[to] = dist[node] + 1;
        dfs(to, node, val);
    }
}

ll lca(ll a, ll b)
{
    if (dist[a] < dist[b])
        swap(a, b);
    while (dist[a] > dist[b])
    {
        if (dist[up[a][1]] >= dist[b])
            a = up[a][1];
        else
            a = up[a][0];
    }
    if (a == b)
        return v4[a];
    while (up[a][0] != up[b][0])
    {
        if (up[a][1] != up[b][1])
        {
            a = up[a][1];
            b = up[b][1];
        }
        else
        {
            a = up[a][0];
            b = up[b][0];
        }
    }
    return v4[up[a][0]];
}

void init(int N, int M, vector<int> U, vector<int> V, vector<int> W)
{
    n = N;
    cnt = N;

    adj.assign(N + M + 10, {});
    up.assign(N + M + 10, vector<ll>(2));
    p.resize(N + 1);
    s.assign(N + 1, 1);
    dg.assign(N + 1, 0);
    v2.assign(N + M + 10, 0);
    v3.resize(N + M + 10);
    v4.resize(N + M + 10);
    dist.assign(N + M + 10, 0);

    iota(p.begin(), p.end(), 0);
    iota(v3.begin(), v3.end(), 0);

    edges.clear();
    for (int i = 0; i < M; i++)
    {
        edges.emplace_back(W[i], V[i], U[i]);
    }

    sort(edges.begin(), edges.end());
    for (auto &[w, y, x] : edges)
        _union(x, y, w);

    up[cnt - 1][0] = up[cnt - 1][1] = cnt - 1;
    dfs(cnt - 1, cnt - 1, -1);
}

int getMinimumFuelCapacity(int X, int Y)
{
    return lca(X, Y);
}
#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...