Submission #445678

# Submission time Handle Problem Language Result Execution time Memory
445678 2021-07-19T09:02:18 Z blue Mergers (JOI19_mergers) C++17
Compilation error
0 ms 0 KB
#include "split.h"
#include <vector>
#include <algorithm>
#include <iostream>
#include <queue>
#include <cassert>
using namespace std;
 
/*
1. Find an arbitrary spanning tree.
2. Find centroid.
3. Find subtree sizes.
4. Check if any subtree has size >= A. If yes, return answer.
5. (2A + B <= N) Using remaining edges, join subtrees.
   If any set of joined subtrees has size >= A, return answer.
6. Return NO.
*/
 
int A, A_index, B, B_index, C, C_index;
 
struct group
{
    int v;
    int i;
};
 
bool operator < (group A, group B)
{
    return A.v < B.v;
}
 
 
const int maxN = 100'000;
vector<int> edge[1+maxN];
int N;
 
 
 
vector<int> st_edge[1+maxN];
vector<int> visit(1+maxN, 0);
 
vector<int> temp_size(1+maxN, 1);
 
void dfs(int u)
{
    visit[u] = 1;
    for(int v: edge[u])
    {
        if(visit[v]) continue;
        st_edge[u].push_back(v);
        st_edge[v].push_back(u);
        dfs(v);
        temp_size[u] += temp_size[v];
    }
}
 
 
 
 
 
 
vector<int> new_size(1+maxN, 1);
 
vector<int> centroid_depth(1+maxN);
 
void new_dfs(int u)
{
    visit[u] = 1;
    for(int v: st_edge[u])
    {
        if(visit[v]) continue;
        centroid_depth[v] = centroid_depth[u] + 1;
        new_dfs(v);
        new_size[u] += new_size[v];
    }
}
 
 
 
 
int centroid;
 
 
vector<int> res;
 
int A_count = 0, B_count = 0;
 
void A_dfs(int u)
{
    if(A_count == A) return;
 
    res[u] = A_index;
    A_count++;
 
    for(int v: st_edge[u])
    {
        if(v == centroid) continue;
        if(res[v] == A_index) continue;
        A_dfs(v);
    }
}
 
void B_dfs(int u)
{
    if(B_count == B) return;
 
    res[u] = B_index;
    B_count++;
 
    for(int v: st_edge[u])
    {
        if(res[v] != C_index) continue;
        B_dfs(v);
    }
}
 
 
 
 
 
 
 
 
 
 
int subtree_ct = 0;
vector<int> subtree_index(1+maxN, 0);
vector<int> subtree_size(1);
 
void final_tree_dfs(int u)
{
    subtree_index[u] = subtree_ct;
    subtree_size[subtree_ct]++;
    for(int v: st_edge[u])
    {
        if(v == centroid || subtree_index[v]) continue;
        final_tree_dfs(v);
    }
}
 
 
 
 
vector<int> extra_edge[1+maxN];
 
 
 
 
 
vector<int> find_split(int n, int a, int b, int c, vector<int> p, vector<int> q)
{
//PART 0: INPUT
    N = n;
    int M = p.size();
    for(int j = 0; j < M; j++)
    {
        edge[ p[j] ].push_back( q[j] );
        edge[ q[j] ].push_back( p[j] );
    }
 
    vector<group> G{group{a, 1}, group{b, 2}, group{c, 3}};
    sort(G.begin(), G.end());
 
    A = G[0].v;
    A_index = G[0].i;
 
    B = G[1].v;
    B_index = G[1].i;
 
    C = G[2].v;
    C_index = G[2].i;
 
 
 
//PART 1: FIND SPANNING TREE.
    dfs(0);
 
    // cerr << "check A\n";
 
 
//PART 2: FIND CENTROID.
    for(centroid = 0; centroid < N; centroid++)
    {
        bool good = 1;
        if(2 * (N - temp_size[centroid]) > N) good = 0;
 
        for(int v: st_edge[centroid])
        {
            if(temp_size[v] > temp_size[centroid]) continue;
            if(2 * temp_size[v] > N) good = 0;
        }
 
        if(good) break;
    }
    // centroid = 0;
 
    // cerr << "check\n";
 
    // cerr << C_index << '\n';
 
 
//PART 3: FIND SUBTREE SIZES
    visit = vector<int>(N, 0);
    centroid_depth[centroid] = 0;
    new_dfs(centroid);
 
//PART 4: CHECK IF ANY SUBTREE HAS SIZE >= A, IF YES RETURN
 
    res = vector<int>(N, C_index);
 
    for(int X: st_edge[centroid])
    {
        if(A <= new_size[X] && B <= N - new_size[X])
        {
            A_dfs(X);
 
            B_dfs(centroid);
 
            // cerr << "case 1\n";
            return res;
        }
    }
 
 
    // if(M == N-1) return vector<int>(N, 0);
 
//PART 5: CHECK IF ANY COMBINATION OF SUBTREES HAVE SIZE >= A.
 
    for(int u: st_edge[centroid])
    {
        subtree_ct++;
        subtree_size.push_back(0);
        final_tree_dfs(u);
    }
 
    for(int j = 0; j < M; j++)
    {
        if(subtree_index[ p[j] ] == subtree_index[ q[j] ]) continue;
        if(p[j] == centroid || q[j] == centroid) continue;
 
        extra_edge[ subtree_index[ p[j] ] ].push_back( subtree_index[ q[j] ] );
        extra_edge[ subtree_index[ q[j] ] ].push_back( subtree_index[ p[j] ] );
    }
 
 
    vector<int> group_visit(1+maxN, 0);
    vector<int> group_size(1+maxN, 0);
    int curr = 0;
    queue<int> tbv;
    vector<bool> added_to_queue(1+maxN, 0);
 
    bool solution_exists = 0;
 
    // cerr << "centroid = " << centroid << '\n';
 
    // cerr << A << '\n';
    vector<int> original_A(1+maxN, 0);
    for(int u = 1; u <= subtree_ct; u++)
    {
        if(group_visit[u]) continue;
 
        curr++;
 
        tbv.push(u);
        added_to_queue[u] = 1;
        while(!tbv.empty())
        {
            int U = tbv.front();
            tbv.pop();
 
            group_visit[U] = curr;
            group_size[curr] += subtree_size[U];
 
 
 
            if(group_size[curr] >= A)
            {
                solution_exists = 1;
                for(int i = 0; i < N; i++)
                {
                    if(group_visit[ subtree_index[i] ] == curr)
                    {
                        // cerr << "original a " << i << '\n';
                        original_A[i] = 1;
                    }
                }
                break;
            }
 
 
            for(int v: extra_edge[U])
            {
                if(group_visit[v]) continue;
 
                if(added_to_queue[v]) continue;
                tbv.push(v);
                added_to_queue[v] = 1;
            }
        }
 
        if(solution_exists) break;
    }
 
 
    if(!solution_exists) return vector<int>(N, 0);
 
    // assert(1 == 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
    res = vector<int>(N, C_index);
    int count_of_A = 0, count_of_B = 0;
 
    added_to_queue = vector<bool>(N, 0);
 
    while(!tbv.empty()) tbv.pop();
    for(int x: st_edge[centroid])
    {
        if(original_A[x])
        {
            tbv.push(x);
            added_to_queue[x] = 1;
            break;
        }
    }
 
    while(!tbv.empty())
    {
        int u = tbv.front();
        tbv.pop();
        // cerr << u << " -> " << A << '\n';
        res[u] = A_index;
        count_of_A++;
        if(count_of_A == A) break;
        for(int v: edge[u])
        {
            // cerr <
            if(original_A[v] && !added_to_queue[v])
            {
                // cerr << u << " ---> " << v << '\n';
                tbv.push(v);
                added_to_queue[v] = 1;
            }
        }
    }
 
    // assert(count_of_)
 
 
 
 
 
 
 
 
 
    while(!tbv.empty()) tbv.pop();
 
    added_to_queue = vector<bool>(N, 0);
 
    tbv.push(centroid);
    added_to_queue[centroid] = 1;
    while(!tbv.empty())
    {
        int u = tbv.front();
        tbv.pop();
 
        res[u] = B_index;
        count_of_B++;
        if(count_of_B == B) break;
        for(int v: edge[u])
        {
            if(res[v] == C_index)
            {
                if(added_to_queue[v]) continue;
                added_to_queue[v] = 1;
                tbv.push(v);
            }
        }
    }
    return res;
}

Compilation message

mergers.cpp:1:10: fatal error: split.h: No such file or directory
    1 | #include "split.h"
      |          ^~~~~~~~~
compilation terminated.