제출 #726042

#제출 시각아이디문제언어결과실행 시간메모리
726042JohannVillage (BOI20_village)C++14
100 / 100
165 ms24096 KiB
#include "bits/stdc++.h"
using namespace std;

typedef long long ll;
typedef pair<ll, ll> pii;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<pii> vpii;
typedef vector<vpii> vvpii;
#define sz(x) (ll)(x).size()
#define all(x) (x).begin(), (x).end()
ll N;
vvi adj;

// Code for the mini length
vi dpP, dpN;
vi ans_mini;
ll miniCheck = 0;

void dfs_mini(ll v, ll p)
{
    if (sz(adj[v]) == 1 && v != p)
    {
        // leaf
        dpN[v] = 0;
        dpP[v] = INT_MAX;
        return;
    }
    for (ll u : adj[v])
        if (u != p)
            dfs_mini(u, v);

    dpN[v] = 0;
    for (ll u : adj[v])
        if (u != p)
            dpN[v] += min(dpP[u], dpN[u] + 2);
    for (ll u : adj[v])
        if (u != p)
        {
            ll tmp = dpN[v] - min(dpP[u], dpN[u] + 2) + min(dpP[u], dpN[u]) + 2;
            dpP[v] = min(dpP[v], tmp);
        }
}
void reconstruct_dpP(ll v, ll p);
void reconstruct_dpN(ll v, ll p, ll except);

void reconstruct_dpN(ll v, ll p, ll except = -1)
{
    if (sz(adj[v]) == 1 && v != p)
        return; // leaf

    for (ll u : adj[v])
    {
        if (u == p)
            continue;
        if (u == except)
        {
            swap(ans_mini[v], ans_mini[u]);
            miniCheck += 2;
            if (dpP[u] < dpN[u])
                reconstruct_dpP(u, v);
            else
                reconstruct_dpN(u, v);
        }
        else if (dpP[u] < dpN[u] + 2)
            reconstruct_dpP(u, v);
        else
        {
            swap(ans_mini[v], ans_mini[u]);
            miniCheck += 2;
            reconstruct_dpN(u, v);
        }
    }
}

void reconstruct_dpP(ll v, ll p)
{
    if (sz(adj[v]) == 1 && v != p)
        return; // leaf

    ll w = -1;
    for (ll u : adj[v])
        if (u != p)
        {
            ll tmp = dpN[v] - min(dpP[u], dpN[u] + 2) + min(dpP[u], dpN[u]) + 2;
            if (dpP[v] == tmp)
            {
                w = u;
                break;
            }
        }
    reconstruct_dpN(v, p, w);
}

// code for the maxi part

vi subsize, swapsRequired;
vvi contains;
vi ans_maxi;
void dfs_maxi(ll v, ll p)
{
    subsize[v] = 1;
    for (ll u : adj[v])
        if (u != p)
        {
            dfs_maxi(u, v);
            subsize[v] += subsize[u];
        }
}
ll find_split(ll v)
{ // v must be root of the tree with respect to subsize
    pii maxSub = {-1, -1};
    for (ll u : adj[v])
        maxSub = max(maxSub, {subsize[u], u});
    if (maxSub.first <= N / 2)
        return v;
    subsize[v] = N - maxSub.first;
    subsize[maxSub.second] = N;
    return find_split(maxSub.second);
}
void collect(ll v, ll p)
{
    contains[v].push_back(v);
    for (ll u : adj[v])
        if (u != p)
        {
            collect(u, v);
            swapsRequired[v] += swapsRequired[u] + subsize[u];
            if (v != p)
            {
                if (sz(contains[u]) > sz(contains[v]))
                    swap(contains[u], contains[v]);
                while (!contains[u].empty())
                    contains[v].push_back(contains[u].back()), contains[u].pop_back();
            }
        }
}
void distribute(ll v)
{
    vi places;
    places.push_back(v);
    for (ll u : adj[v])
        places.push_back(u);
    sort(all(places), [&](ll a, ll b)
         { return sz(contains[a]) > sz(contains[b]); });
    queue<ll> todo;
    for (ll u : places)
        for (ll w : contains[u])
            todo.push(w);
    for (ll i = 0; i < sz(places); ++i)
        for (ll u : contains[places[(i + 1) % sz(places)]])
            ans_maxi[u] = todo.front(), todo.pop();
}

// main
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> N;
    adj.resize(N);
    for (ll i = 0, a, b; i < N - 1; ++i)
    {
        cin >> a >> b, --a, --b;
        adj[a].push_back(b), adj[b].push_back(a);
    }

    // mini
    dpP.assign(N, INT_MAX), dpN.assign(N, INT_MAX);
    dfs_mini(0, 0);

    ans_mini.resize(N);
    iota(all(ans_mini), 1);
    reconstruct_dpP(0, 0);

    // maxi
    subsize.resize(N);
    dfs_maxi(0, 0);
    ll center = find_split(0);
    contains.resize(N);
    swapsRequired.assign(N, 0);
    collect(center, center);
    ans_maxi.resize(N);
    distribute(center);

    // ans
    cout << dpP[0] << " ";
    cout << 2 * swapsRequired[center] << endl;
    assert(miniCheck == dpP[0]);
    for (ll v : ans_mini)
        cout << v << " ";
    cout << endl;

    for (ll v : ans_maxi)
        cout << v + 1 << " ";
    cout << endl;

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...