제출 #915359

#제출 시각아이디문제언어결과실행 시간메모리
915359Alcabel통행료 (APIO13_toll)C++17
100 / 100
1114 ms14072 KiB
#include <bits/stdc++.h>
using namespace std;

struct DSU {
    int n;
    vector<int> par, sz;
    DSU() {}
    DSU(int _n) {
        n = _n;
        par.resize(n);
        sz.resize(n);
        clear();
    }
    void clear() {
        for (int i = 0; i < n; ++i) {
            par[i] = i, sz[i] = 1;
        }
    }
    int getParent(int v) {
        if (par[v] != v) {
            par[v] = getParent(par[v]);
        }
        return par[v];
    }
    bool uniteSets(int v, int u) {
        v = getParent(v), u = getParent(u);
        if (v == u) { return false; }
        if (sz[v] < sz[u]) { swap(v, u); }
        par[u] = v;
        sz[v] += sz[u];
        return true;
    }
    ~DSU() {}
};

struct Edge {
    int v, u, w;
    Edge() {}
    Edge(int _v, int _u, int _w) {
        v = _v, u = _u, w = _w;
    }
    bool operator<(const Edge& other) const {
        return w < other.w;
    }
    ~Edge() {}
};

vector<vector<pair<int, int>>> g;
vector<int> h, parW, par;
vector<long long> compP, sumP;

void dfsPrecalc(int v) {
    sumP[v] = compP[v];
    for (const auto& [u, newW] : g[v]) {
        if (u != par[v]) {
            parW[u] = newW;
            par[u] = v;
            h[u] = h[v] + 1;
            dfsPrecalc(u);
            sumP[v] += sumP[u];
        }
    }
    // cerr << "v: " << v << ", sumP: " << sumP[v] << ", compP: " << compP[v] << '\n';
}

void minEq(int v, int u, int w) {
    if (h[v] < h[u]) {
        swap(v, u);
    }
    while (h[v] > h[u]) {
        parW[v] = min(parW[v], w);
        v = par[v];
    }
    while (v != u) {
        parW[v] = min(parW[v], w);
        parW[u] = min(parW[u], w);
        v = par[v], u = par[u];
    }
}

long long dfsAns(int v) {
    long long res = parW[v] * sumP[v];
    for (const auto& [u, newW] : g[v]) {
        if (u != par[v]) {
            res += dfsAns(u);
        }
    }
    return res;
}

void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    vector<Edge> edges(m);
    for (int i = 0; i < m; ++i) {
        int v, u, w;
        cin >> v >> u >> w;
        --v, --u;
        edges[i] = Edge(v, u, w);
    }
    vector<Edge> additional(k);
    DSU with(n);
    for (int i = 0; i < k; ++i) {
        int v, u;
        cin >> v >> u;
        --v, --u;
        additional[i] = Edge(v, u, 1000001);
        with.uniteSets(v, u);
    }
    vector<int> p(n);
    for (int i = 0; i < n; ++i) {
        cin >> p[i];
    }
    sort(edges.begin(), edges.end());
    DSU without(n);
    // cerr << "!\n";
    vector<Edge> mstEdges;
    for (int i = 0; i < m; ++i) {
        if (without.uniteSets(edges[i].v, edges[i].u)) {
            mstEdges.emplace_back(edges[i]);
        }
    }
    // cerr << "!\n";
    without.clear();
    vector<Edge> sus;
    for (const Edge& e : mstEdges) {
        if (with.getParent(e.v) != with.getParent(e.u)) {
            without.uniteSets(e.v, e.u);
        } else {
            sus.emplace_back(e);
        }
        with.uniteSets(e.v, e.u);
    }
    // cerr << "!\n";
    assert((int)sus.size() <= k);
    vector<int> compOf(n, -1);
    int comps = 0;
    for (int i = 0; i < n; ++i) {
        if (compOf[without.getParent(i)] == -1) {
            compOf[without.getParent(i)] = comps++;
            compP.emplace_back(0);
        }
        int c = compOf[without.getParent(i)];
        compOf[i] = c;
        compP[c] += p[i];
    }
    g.resize(comps);
    h.resize(comps);
    sumP.resize(comps);
    par.resize(comps);
    parW.resize(comps);
    for (Edge& e : sus) {
        e.v = compOf[e.v];
        e.u = compOf[e.u];
        assert(e.v != e.u);
    }
    for (Edge& e : additional) {
        e.v = compOf[e.v];
        e.u = compOf[e.u];
        assert(e.v != e.u);
    }
    long long ans = 0;
    DSU comp(comps);
    vector<Edge> limits;
    /*cerr << "!\n";
    for (int i = 0; i < n; ++i) {
        cerr << "i: " << i << ", compOf: " << compOf[i] << '\n';
    }*/
    for (int mask = 1; mask < (1 << k); ++mask) {
        comp.clear();
        for (int i = 0; i < comps; ++i) {
            g[i].clear();
        }
        bool hasCycle = false;
        for (int i = 0; i < k; ++i) {
            if (mask & (1 << i)) {
                if (!comp.uniteSets(additional[i].v, additional[i].u)) {
                    hasCycle = true;
                    break;
                }
                g[additional[i].v].emplace_back(additional[i].u, additional[i].w);
                g[additional[i].u].emplace_back(additional[i].v, additional[i].w);
            }
        }
        if (hasCycle) {
            continue;
        }
        // cerr << "mask: " << mask << ", dont have a cycle\n";
        limits.clear();
        for (const Edge& e : sus) {
            if (comp.uniteSets(e.v, e.u)) {
                g[e.v].emplace_back(e.u, 0);
                g[e.u].emplace_back(e.v, 0);
            } else {
                limits.emplace_back(e);
            }
        }
        h[compOf[0]] = 0;
        par[compOf[0]] = -1;
        parW[compOf[0]] = 0;
        // cerr << "dfsPrecalc:\n";
        dfsPrecalc(compOf[0]);
        for (const Edge& e : limits) {
            minEq(e.v, e.u, e.w);
        }
        ans = max(ans, dfsAns(compOf[0]));
    }
    cout << ans << '\n';
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
        cerr << "-----------\n";
        cout << "-----------\n";
    }
#else
    int T = 1;
    // cin >> T;
    while (T--) {
        solve();
    }
#endif

    return 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...