Submission #1217443

#TimeUsernameProblemLanguageResultExecution timeMemory
1217443_callmelucian자매 도시 (APIO20_swap)C++17
100 / 100
186 ms54156 KiB
#include <bits/stdc++.h>
#ifndef LOCAL
    #include "swap.h"
#endif // LOCAL
using namespace std;

using ll = long long;
using ld = long double;
using pl = pair<ll,ll>;
using pii = pair<int,int>;
using tpl = tuple<int,int,int>;

#define all(a) a.begin(), a.end()
#define filter(a) a.erase(unique(all(a)), a.end())

struct DSU {
    vector<int> lab, contain, id;
    int counter;

    DSU (int sz) : lab(sz + 1, -1), contain(sz + 1),
                   id(sz + 1), counter(sz) { iota(all(id), 0); }

    int get (int u) {
        if (lab[u] < 0) return u;
        return lab[u] = get(lab[u]);
    }

    int getID (int u) { return id[get(u)]; }
    bool good (int u) { return contain[get(u)]; }

    bool unite (int a, int b) {
        a = get(a), b = get(b);
        if (a == b)
            return contain[a] = 1, id[a] = ++counter, 0;
        if (-lab[a] < -lab[b]) swap(a, b);
        lab[a] += lab[b], lab[b] = a;
        contain[a] |= contain[b], id[a] = ++counter;
        return 1;
    }

    void setNode (int u) { contain[get(u)] = 1; }
};

const int mn = 3e5 + 5;
int up[mn][20], curDeg[mn], depth[mn], weight[mn], n, m;
bool good[mn], vis[mn];
vector<int> adj[mn];
vector<tpl> edges;

void dfs (int u, int p, int d) {
    up[u][0] = p, depth[u] = d;
    for (int i = 1; i < 20; i++)
        up[u][i] = up[up[u][i - 1]][i - 1];
    for (int v : adj[u]) dfs(v, u, d + 1);
}

void init (int N, int M, vector<int> U, vector<int> V, vector<int> W) {
    n = N, m = M;
    for (int i = 0; i < m; i++)
        edges.emplace_back(W[i], U[i] + 1, V[i] + 1);
    sort(all(edges));

    /// build kruskal reconstruction tree
    DSU dsu(n);
    for (int i = 0; i < m; i++) {
        int a, b, c; tie(c, a, b) = edges[i];
        int u = dsu.getID(a), v = dsu.getID(b);
        if (!u) cout << "troi oi " << a << endl;
        if (!v) cout << "troi oi " << b << endl;

        // mark special nodes
        if (++curDeg[a] == 3) dsu.setNode(a);
        if (++curDeg[b] == 3) dsu.setNode(b);


        // merge component
        bool connected = dsu.unite(a, b);
        int cur = dsu.getID(a);
        adj[cur].push_back(u);
        if (connected)
            adj[cur].push_back(v);

        weight[cur] = c, good[cur] = dsu.good(a);
    }
    weight[0] = -1, good[0] = 1;

//    for (int i = 1; i <= n + m; i++) {
//        cout << "node " << i << ": ";
//        for (int j : adj[i]) cout << j << " ";
//        cout << "\n";
//    }

    /// run dfs
    for (int i = 1; i <= n; i++) {
        int u = dsu.getID(i);
        if (!vis[u]) dfs(u, 0, 0), vis[u] = 1;
    }
}

int goUp (int a, int k) {
    for (int i = 0; k; i++, k >>= 1)
        if (k & 1) a = up[a][i];
    return a;
}

int lca (int a, int b) {
    if (depth[a] < depth[b]) swap(a, b);
    a = goUp(a, depth[a] - depth[b]);
    if (a == b && good[a]) return a;
    for (int i = 19; i >= 0; i--)
        if (up[a][i] != up[b][i] || !good[up[a][i]]) a = up[a][i], b = up[b][i];
    return up[a][0];
}

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