Submission #798539

#TimeUsernameProblemLanguageResultExecution timeMemory
798539PanosPaskTorrent (COI16_torrent)C++14
100 / 100
1068 ms47900 KiB
#include <bits/stdc++.h>
#define pb push_back

using namespace std;

int N, A, B;

// dp[i]: Maximum allowed time s.t i must be reached in order to complete the thing in time
vector<int> dp;
vector<int> p;
vector<bool> ok;
vector<vector<int>> adj_list;
vector<vector<int>> kid_times;

int TIME_TESTED;

vector<int> tin;
vector<int> tout;
int counter;

bool ancestor(int a, int b)
{
    return tin[a] <= tin[b] && tout[a] >= tout[b];
}

bool test_early(int t, vector<int>& a, int skiptime = -2)
{
    int cur_time = t;
    for (int i = 0; i < a.size(); i++) {
        if (cur_time == skiptime)
            cur_time++;
        if (a[i] < cur_time)
            return false;
        cur_time++;
    }

    return true;
}

void push_downwards(int node, int time_par)
{
    if (!ancestor(node, B)) {
        return;
    }
    else if (test_early(time_par, kid_times[node]) == false) {
        // Cannot advance
        return;
    }

    ok[node] = true;
    // Find the earliest time the file can be sent to the child that leads to B
    int l = time_par;
    int r = TIME_TESTED + 1;
    while (r > l + 1) {
        int mid = (l + r) / 2;
        if (test_early(time_par, kid_times[node], mid))
            r = mid;
        else
            l = mid;
    }

    for (auto neigh : adj_list[node])
        if (neigh != p[node])
            push_downwards(neigh, r);
}

// Function to be called at B and ancestors
// Seeing at what time they can get the file
void push_upwards(int node, int time_kid)
{
    if (node == -1) {
        return;
    }
    else if (test_early(time_kid, kid_times[node]) == false) {
        // Cannot go here, or further
        return;
    }

    ok[node] = true;
    // Find the earliest time the file can be sent to the parent
    // Find the earliest time the file can be sent to the child that leads to B
    int l = time_kid;
    int r = TIME_TESTED + 1;
    while (r > l + 1) {
        int mid = (l + r) / 2;
        if (test_early(time_kid, kid_times[node], mid))
            r = mid;
        else
            l = mid;
    }

    push_upwards(p[node], r);
}

void calculate_dp(int node)
{
    kid_times[node].push_back(TIME_TESTED + 1);
    for (auto neigh : adj_list[node]) {
        if (neigh == p[node])
            continue;

        calculate_dp(neigh);

        if (!ancestor(neigh, B))
            kid_times[node].push_back(dp[neigh]);
    }

    sort(kid_times[node].begin(), kid_times[node].end());
    // Binary search for the latest possible time slot
    int r = TIME_TESTED + 1;
    int l = -1;
    while (r > l + 1) {
        int mid = (l + r) / 2;
        if (test_early(mid, kid_times[node]))
            l = mid;
        else
            r = mid;
    }

    // The earliest time is l - 1
    dp[node] = l - 1;

    return;
}

void euler_tour(int node)
{
    tin[node] = counter++;

    for (auto neigh : adj_list[node]) {
        if (neigh != p[node]) {
            p[neigh] = node;
            euler_tour(neigh);
        }
    }

    tout[node] = counter;
}

bool test_time(int t)
{
    TIME_TESTED = t;
    ok.assign(N, false);
    kid_times.assign(N, vector<int>());
    dp.assign(N, -1);

    calculate_dp(A);
    push_downwards(A, 0);
    push_upwards(B, 0);

    for (int i = 0; i < N; i++) {
        if (ancestor(i, B) && !ok[i])
            return false;
    }

    return true;
}

int main(void)
{
    scanf("%d %d %d", &N, &A, &B);
    A--; B--;

    tin.resize(N);
    tout.resize(N);
    dp.resize(N);
    p.resize(N);
    adj_list.resize(N);
    for (int i = 0; i < N - 1; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        u--; v--;

        adj_list[u].pb(v);
        adj_list[v].pb(u);
    }

    // Root the tree at A
    p[A] = -1;
    euler_tour(A);

    int l = -1;
    int r = N;
    while (r > l + 1) {
        int mid = (l + r) / 2;
        if (test_time(mid))
            r = mid;
        else
            l = mid;
    }

    printf("%d\n", r);

    return 0;
}

Compilation message (stderr)

torrent.cpp: In function 'bool test_early(int, std::vector<int>&, int)':
torrent.cpp:29:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   29 |     for (int i = 0; i < a.size(); i++) {
      |                     ~~^~~~~~~~~~
torrent.cpp: In function 'int main()':
torrent.cpp:161:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  161 |     scanf("%d %d %d", &N, &A, &B);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
torrent.cpp:171:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  171 |         scanf("%d %d", &u, &v);
      |         ~~~~~^~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...