제출 #1287496

#제출 시각아이디문제언어결과실행 시간메모리
1287496Ice_manRace (IOI11_race)C++17
0 / 100
8 ms12208 KiB
/**
 ____    ____    ____    __________________    ____    ____    ____
||I ||  ||c ||  ||e ||  ||                ||  ||M ||  ||a ||  ||n ||
||__||  ||__||  ||__||  ||________________||  ||__||  ||__||  ||__||
|/__\|  |/__\|  |/__\|  |/________________\|  |/__\|  |/__\|  |/__\|

*/

#include <iostream>
#include <vector>
#include <map>

#include "race.h"

#define maxn 500005
#define PB push_back
#define X first
#define Y second

typedef long long ll;
typedef std::pair <ll, ll> pll;

const ll INF = 4e18;

std::vector<pll> v[maxn];
int n, k;
ll ans;

// We'll use DFS small-to-large per-node maps (distances measured from the node)
std::map<ll,ll>* mp[maxn];

void dfs_sl(int node, int par)
{
    // create map for node: distance 0 -> edges count 0
    mp[node] = new std::map<ll,ll>();
    mp[node]->emplace(0LL, 0LL);

    for (auto &nb : v[node])
    {
        int to = (int)nb.X;
        ll w = nb.Y;
        if (to == par) continue;

        dfs_sl(to, node);

        // ensure mp[node] is the larger map (small-to-large)
        if (mp[node]->size() < mp[to]->size())
        {
            // swap pointers: node's map becomes child's map and vice versa
            std::swap(mp[node], mp[to]);

            // the map now in mp[node] has distances relative to 'to' not 'node'
            // shift all keys in mp[node] by +w and add +1 to values (edges count)
            std::map<ll,ll>* shifted = new std::map<ll,ll>();
            for (auto &pr : *mp[node])
            {
                ll newd = pr.first + w;
                ll newv = pr.second + 1;
                auto it = shifted->find(newd);
                if (it == shifted->end()) shifted->emplace(newd, newv);
                else it->second = std::min(it->second, newv);
            }
            delete mp[node];
            mp[node] = shifted;
        }
        else
        {
            // mp[node] is the larger; merge mp[to] into mp[node]
            // query complements first
            for (auto &pr : *mp[to])
            {
                ll dist_from_node = pr.first + w;
                ll edges_cnt = pr.second + 1;
                ll need = (ll)k - dist_from_node;
                auto it = mp[node]->find(need);
                if (it != mp[node]->end())
                    ans = std::min(ans, it->second + edges_cnt);
            }
            // insert shifted entries
            for (auto &pr : *mp[to])
            {
                ll newd = pr.first + w;
                ll newv = pr.second + 1;
                auto it = mp[node]->find(newd);
                if (it == mp[node]->end()) mp[node]->emplace(newd, newv);
                else it->second = std::min(it->second, newv);
            }
            delete mp[to];
            mp[to] = nullptr;
            continue;
        }

        // after swapping, merge the smaller map (old mp[to]) into new mp[node]
        for (auto &pr : *mp[to])
        {
            ll dist_from_node = pr.first + w;
            ll edges_cnt = pr.second + 1;
            auto it = mp[node]->find((ll)k - dist_from_node);
            if (it != mp[node]->end())
                ans = std::min(ans, it->second + edges_cnt);
        }
        for (auto &pr : *mp[to])
        {
            ll newd = pr.first + w;
            ll newv = pr.second + 1;
            auto it = mp[node]->find(newd);
            if (it == mp[node]->end()) mp[node]->emplace(newd, newv);
            else it->second = std::min(it->second, newv);
        }
        delete mp[to];
        mp[to] = nullptr;
    }

    // check if there's a path of distance exactly k within subtree
    auto it = mp[node]->find((ll)k);
    if (it != mp[node]->end())
        ans = std::min(ans, it->second);
}

int best_path(int N, int K, int h[][2], int L[])
{
    n = N;
    k = K;
    ans = INF;

    // clear adjacency
    for (int i = 1; i <= n; ++i) v[i].clear();

    for (int i = 0; i < n - 1; ++i)
    {
        v[h[i][0] + 1].PB({h[i][1] + 1, L[i]});
        v[h[i][1] + 1].PB({h[i][0] + 1, L[i]});
    }

    for (int i = 0; i <= n; ++i) mp[i] = nullptr;

    dfs_sl(1, 0);

    if (mp[1]) { delete mp[1]; mp[1] = nullptr; }

    if (ans == INF) return -1;
    else return (int)ans; // ans stores number of edges directly
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...