제출 #1177122

#제출 시각아이디문제언어결과실행 시간메모리
1177122iulia_morariu경주 (Race) (IOI11_race)C++20
100 / 100
1077 ms64304 KiB
#include <algorithm>
#include <iostream>
#include <fstream>
#include <climits>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include "race.h"
//#include <bits/stdc++.h>
#define in  cin
#define out cout
#define mkp make_pair

using namespace std;
using ll = long long;

ifstream fin("test.in");

ll n, k, mini = -1;
vector<int> g[200001], d[200001];
int dim[200001]; // size (local calculat) (you'll see)
int dp[200001]; // dp[i] = dim max a unui subarb daca il elimin pe i (tot local) (you'll also see)
bool acc[200001];

void det_size(int nod, int f){
    dim[nod] = 0;
    for(int cop : g[nod]){
        if(cop == f || !acc[cop]) continue;
        det_size(cop, nod);
        dim[nod] += dim[cop];
    }
    dim[nod]++;
}

void det_dp(int nod, int f, int size_subt){
    dp[nod] = size_subt - dim[nod];
    for(int cop : g[nod]){
        if(cop == f || !acc[cop]) continue;
        det_dp(cop, nod, size_subt);
        dp[nod] = max(dp[nod], dim[cop]);
    }
}

int centroidul(int nod, int f, int size_subt){
    if(dp[nod] <= size_subt / 2) return nod;
    for(int cop : g[nod]){
        if(cop == f || !acc[cop]) continue;
        int cc = centroidul(cop, nod, size_subt);
        if(cc != -1) return cc;
    }
    return -1;
}

void mergeLeft(map< ll, int > & a, map< ll, int > & b, int add, int addL){
    for(auto i : b){
        if(i.first + add > k || (mini != -1 && i.second + addL > mini)) continue;
        auto it = a.find(i.first + add);
        if(it == a.end()) a[ i.first + add ] = i.second + addL;
        else (*it).second = min((*it).second, i.second + addL);
    }
}

void drumuri(int nod, int f, map<ll, int> & mp, int offset, int len){ // offset = cat e drumul de la root la mine
    if(offset > k) return;
    if(mini != -1 && len > mini) return;
    
    if(mp.find(offset) != mp.end()) mp[offset] = min(mp[offset], len);
    else mp[offset] = len;

    // cout << "DRUMURI : Am ajuns la " << nod << " parintele " << f << " map (mp) offset = " << offset << " len = " << len << '\n';

    int poz = 0;
    for(int cop : g[nod]){
        if(cop == f || !acc[cop]){ poz++; continue; }
        drumuri(cop, nod, mp, offset + d[nod][poz], len + 1);
        poz++;
    }
}

void proc_arb(int nod){
    // cout << "Procesam subarborele lui " << nod << '\n';
    // cerr << "Start " << nod << '\n';
    det_size(nod, -1); det_dp(nod, -1, dim[nod]);
    int cen = centroidul(nod, -1, dim[nod]);
    // cerr << "End preprocesare " << nod << '\n';
    if(cen == -1) cen = nod;
    // cout << "  -- > dp : " << dp[1] << " size = " << dim[1] << '\n';
    // cout << "  -- > gasim centroidul ca " << cen << '\n';
    acc[cen] = 0;

    // gasim mapurile
    int poz = 0;
    // cerr << "Incepem det " << nod << '\n';
    map<ll, int> general;
    for(int cop : g[cen]){
        if(!acc[cop]){ poz++; continue;}
        map<ll, int> mp;
        drumuri(cop, cen, mp, d[cen][poz], 1);

        // cout << "  -- > cop = " << cop << " mp = \n";
        // for(auto i : mp){
        //     cout << "    -- > " << i.first << " , " << i.second << '\n';
        // }

        for(auto i : mp){
            // cout << "  -- > pentru " << i.first << " , " << i.second << " am nevoie de suma " << k - i.first << '\n';
            if(general.find( k - i.first ) == general.end()) continue;
            int len = general[k - i.first ] + i.second;
            // cout << "  -- > Gasesc drum de lungime " << len << '\n';
            if(mini == -1 || mini > len) mini = len;
        }
        
        mergeLeft(general, mp, 0, 0);
        poz++;
    }
    // cerr << "Termin determinarea " << nod << '\n';

    // cout << "In general : \n";
    // for(auto i : general){
    //     cout << "    -- > " << i.first << " , " << i.second << '\n';
    // }

    if( general.find(k) != general.end() && (mini == -1 || general[k] < mini) ) mini = general[k];

    for(int cop : g[cen]){
        if(!acc[cop]) continue;
        proc_arb(cop);
    }
}

int best_path(int N, int K, int H[][2], int L[]){
    n = N; k = K;
    for(int i = 0; i < n; i++) acc[i] = 1;
    // cerr << "Start\n";
    for(int i = 0; i < N - 1; i++){
        g[ H[i][0] ].push_back( H[i][1] );
        g[ H[i][1] ].push_back( H[i][0] );

        d[ H[i][0] ].push_back( L[i] );
        d[ H[i][1] ].push_back( L[i] );
    }
    // cerr << "End\n";

    proc_arb(0);
    return mini;
}

// signed main(){
//     ios_base::sync_with_stdio(false);
//     cin.tie(NULL);

//     int n, k; in >> n >> k;
//     int H[n - 1][2], L[n - 1];

//     for(int i = 0; i < n - 1; i++) in >> H[i][0] >> H[i][1] >> L[i];
//     // for(int i = 0; i < n - 1; i++) in >> L[i];

//     out << best_path(n, k, H, L) << '\n';

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