제출 #445678

#제출 시각아이디문제언어결과실행 시간메모리
445678blueMergers (JOI19_mergers)C++17
컴파일 에러
0 ms0 KiB
#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; }

컴파일 시 표준 에러 (stderr) 메시지

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