This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include "simurgh.h"
#include <bits/stdc++.h>
#define pb push_back
#define f first
#define sc second
using namespace std;
typedef long long int ll;
typedef string str;
struct dsu{
int n;
vector<int> sz, p;
dsu(int _n): n(_n){
sz.resize(n, 1);
p.resize(n);
for(int i = 0; i < n; i++) p[i] = i;
}
int get(int x){
if(p[x] != x) p[x] = get(p[x]);
return p[x];
}
bool unite(int a, int b){
a = get(a), b = get(b);
if(a == b) return 0;
if(sz[b] > sz[a]) swap(a, b);
sz[a]+=sz[b];
sz[b] = 0;
p[b] = a;
return 1;
}
};
int n, m;
vector<int> U, V;
vector<int> royal;
vector<vector<pair<int, int>>> graph;
int count_common_roads(const basic_string<int>& E){
vector<int> EE;
for(int x: E) EE.pb(x);
return count_common_roads(EE);
}
basic_string<int> generate_tree(const basic_string<int>& E){
dsu ds(n);
basic_string<int> T;
for(int i: E){
if(ds.unite(U[i], V[i])) T.pb(i);
else return {};
}
for(int i = 0; i < m; i++) if(ds.unite(U[i], V[i])) T.pb(i);
return T;
}
pair<basic_string<int>,basic_string<int>> forcefully_generate_tree(const basic_string<int>& E){
dsu ds(n);
basic_string<int> T, I;
for(int i: E){
if(ds.unite(U[i], V[i])) T.pb(i);
else I.pb(i);
}
for(int i = 0; i < m; i++) if(ds.unite(U[i], V[i])) T.pb(i);
return {T, I};
}
int replacement_edge(const basic_string<int>& E, int i){
dsu ds(n);
for(int j: E) if(j != i) ds.unite(U[j], V[j]);
for(int j = 0; j < m; j++) if(j != i && ds.unite(U[j], V[j])) return j;
return -1;
}
int count_extra_royal(const basic_string<int>& T, basic_string<int> C){
dsu ds(n);
int c = 0;
vector<int> q;
for(int i: C) ds.unite(U[i], V[i]), q.pb(i);
for(int i: T) if(ds.unite(U[i], V[i])) c+=max(royal[i], 0), q.pb(i);
return count_common_roads(q)-c;
}
vector<int> find_roads(int _n, vector<int> _U, vector<int> _V){
swap(n, _n), swap(U, _U), swap(V, _V);
m = U.size();
royal.assign(m, -1);
graph.resize(n);
for(int i = 0; i < m; i++){
graph[U[i]].pb({V[i], i});
graph[V[i]].pb({U[i], i});
}
basic_string<int> A, B = {0};
while(1){
int x, y, z;
int ei = int(A.size()+B.size())-1, e = B.back();
if(A.size()+B.size() == n-1){
int cnt = 0;
for(int i: A) if(royal[i] == 1) cnt++;
int x = count_common_roads(A+B);
A+=B;
for(int i: B) royal[i] = (x > cnt);
break;
}
auto T = generate_tree(A+B);
int i = replacement_edge(T, e);
if(i == -1){
for(int j: B) royal[j] = 1;
goto finalize;
}
x = count_common_roads(T);
T[ei] = i;
y = count_common_roads(T);
T[ei] = e;
if(x > y){
for(int j: B) royal[j] = 1;
royal[i] = 0;
goto finalize;
}
else if(x < y){
for(int j: B) royal[j] = 0;
royal[i] = 1;
goto finalize;
}
else{
if(royal[i] != -1){
for(int j: B) royal[j] = royal[i];
goto finalize;
}
if(generate_tree(A+B+i).empty()){
if(generate_tree(B+i).empty()){
for(int j: B) royal[j] = 0;
royal[i] = 0;
goto finalize;
}
auto [T2, I] = forcefully_generate_tree(B+i+A);
z = count_common_roads(T2);
if(z > x){
for(int j: B) royal[j] = 1;
}
else if(z < x){
for(int j: B) royal[j] = 0;
}
else{
for(int j: B) royal[j] = royal[I[0]];
}
goto finalize;
}
else{
B.pb(i);
continue;
}
}
finalize:
A+=B;
B.clear();
if(A.size() + B.size() == n-1) break;
B+=T[A.size()+B.size()];
}
vector<int> ans;
for(int i = 0; i < m; i++) if(royal[i] == 1) ans.pb(i);
for(int nd = 0; nd < n; nd++){
basic_string<int> S;
for(auto [x, i]: graph[nd]) if(royal[i] == -1) S.pb(i);
if(S.empty()) continue;
int X = count_extra_royal(A, S);
while(X > 0){
int a = 1, b = S.size();
while(a < b){
int md = (a+b)/2;
if(count_extra_royal(A, S.substr(0, md)) >= X) b = md;
else a = md+1;
}
royal[S[a-1]] = 1;
ans.pb(S[a-1]);
X--;
}
for(int i: S) if(royal[i] == -1) royal[i] = 0;
}
return ans;
}
Compilation message (stderr)
simurgh.cpp: In function 'std::vector<int> find_roads(int, std::vector<int>, std::vector<int>)':
simurgh.cpp:94:30: warning: comparison of integer expressions of different signedness: 'std::__cxx11::basic_string<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
94 | if(A.size()+B.size() == n-1){
| ~~~~~~~~~~~~~~~~~~^~~~~~
simurgh.cpp:158:32: warning: comparison of integer expressions of different signedness: 'std::__cxx11::basic_string<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
158 | if(A.size() + B.size() == n-1) break;
| ~~~~~~~~~~~~~~~~~~~~^~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |