답안 #685676

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
685676 2023-01-24T19:20:03 Z finn__ Training (IOI07_training) C++17
20 / 100
12 ms 1548 KB
#include <bits/stdc++.h>
using namespace std;

struct Edge
{
    uint64_t u, v, w;
};

vector<vector<uint64_t>> g, anc;
vector<uint64_t> height, ind;
vector<vector<Edge>> unpaved;
vector<vector<uint64_t>> dp;

uint64_t lift(uint64_t u, uint64_t h)
{
    uint64_t z = 0;
    while (h)
    {
        if (h & 1)
        {
            assert(z < anc[u].size());
            u = anc[u][z];
        }
        h >>= 1;
        z++;
    }
    return u;
}

uint64_t lca(uint64_t u, uint64_t v)
{
    assert(u < g.size() && v < g.size());
    if (height[u] < height[v])
        swap(u, v);
    u = lift(u, height[u] - height[v]);
    if (u == v)
        return u;

    for (uint64_t i = anc[u].size() - 1; i < anc[u].size(); i--)
    {
        if (anc[u][i] != anc[v][i])
        {
            u = anc[u][i];
            v = anc[v][i];
        }
    }

    return anc[u][0];
}

void traverse(uint64_t u, vector<uint64_t> &path, uint64_t p = -1, uint64_t h = 0)
{
    for (uint64_t i = 1; i <= path.size(); i <<= 1U)
        anc[u].push_back(path[path.size() - i]);
    height[u] = h;
    path.push_back(u);

    for (uint64_t const &v : g[u])
        if (v != p)
            traverse(v, path, u, h + 1);

    path.pop_back();
}

void calc_dp(uint64_t u)
{
    for (uint64_t const &v : g[u])
    {
        calc_dp(v);
    }

    dp[u] = vector<uint64_t>(1U << g[u].size());
    // Case 1. Just delete the root and add up subtree values.
    for (uint64_t z = 0; z < (1U << g[u].size()); z++)
    {
        dp[u][z] = 0;
        for (uint64_t i = 0; i < g[u].size(); i++)
        {
            if (!(z & (1U << i)))
            {
                dp[u][z] += dp[g[u][i]][0];
            }
        }
    }

    for (uint64_t i = 0; i < g[u].size(); i++)
    {
        ind[g[u][i]] = i;
    }

    // Case 2: Take exactly one unpaved road whose tree path contains u.
    for (auto const &[a, b, w] : unpaved[u])
    {
        // Stores just the value obtained from the two used subtrees.
        uint64_t x = 0;
        if (a != u)
        {
            x += dp[a][0];
            uint64_t r = a, s = anc[a][0];
            while (s != u)
            {
                // assert(dp[s].size() == 1U << g[s].size());
                x += dp[s][1U << ind[r]];
                r = s;
                s = anc[s][0];
            }
        }
        if (b != u)
        {
            x += dp[b][0];
            uint64_t r = b, s = anc[b][0];
            while (s != u)
            {
                x += dp[s][1U << ind[r]];
                r = s;
                s = anc[s][0];
            }
        }

        uint64_t p = UINT_MAX, q = UINT_MAX;

        if (a != u)
            p = ind[lift(a, height[a] - height[u] - 1)];
        if (b != u)
            q = ind[lift(b, height[b] - height[u] - 1)];

        for (uint64_t z = 0; z < (1U << g[u].size()); z++)
        {
            if ((a != u && (z & (1U << p))) || (b != u && (z & (1U << q))))
                continue;

            uint64_t y = 0;
            // Sum all children not on an edge path and not ruled out.
            for (uint64_t i = 0; i < g[u].size(); i++)
            {
                if (!(z & (1U << i)) && i != p && i != q)
                {
                    y += dp[g[u][i]][0];
                }
            }
            dp[u][z] = max(dp[u][z], x + y + w);
        }
    }
}

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

    size_t n, m;
    cin >> n >> m;

    g = vector<vector<uint64_t>>(n);
    vector<Edge> unpaved_edges;
    uint64_t total_cost = 0;

    for (size_t i = 0; i < m; i++)
    {
        uint64_t u, v, w;
        cin >> u >> v >> w;
        total_cost += w;

        if (!w)
        {
            g[u - 1].push_back(v - 1);
            g[v - 1].push_back(u - 1);
        }
        else
        {
            unpaved_edges.push_back({u - 1, v - 1, w});
        }
    }

    height = vector<uint64_t>(n);
    anc = vector<vector<uint64_t>>(n);
    vector<uint64_t> path;
    traverse(0, path);

    for (uint64_t u = 0; u < n; u++)
    {
        for (auto it = g[u].begin(); it != g[u].end(); it++)
        {
            if (!anc[u].empty() && *it == anc[u][0])
            {
                g[u].erase(it);
                break;
            }
        }
    }

    unpaved = vector<vector<Edge>>(n);
    for (auto const &[u, v, w] : unpaved_edges)
    {
        if (!((height[u] + height[v]) & 1))
        {
            assert(lca(u, v) < n);
            unpaved[lca(u, v)].push_back({u, v, w});
        }
    }

    dp = vector<vector<uint64_t>>(n);
    ind = vector<uint64_t>(n);
    calc_dp(0);

    cout << total_cost - dp[0][0] << '\n';
}
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 340 KB Output is correct
2 Correct 1 ms 340 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Runtime error 2 ms 1152 KB Execution killed with signal 11
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 0 ms 212 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 1 ms 212 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 1 ms 340 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 1 ms 340 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 2 ms 468 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 6 ms 1372 KB Execution killed with signal 11
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 12 ms 724 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 7 ms 1548 KB Execution killed with signal 11
2 Halted 0 ms 0 KB -