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 <bits/stdc++.h>
#include "icc.h"
using namespace std;
typedef vector<int> vi;
const int MAXN = 110;
struct UnionFind{
vi p, rank;
vector<vi> members;
int N;
UnionFind(int _N) {
N = _N;
p.assign(N+1, 0);
rank.assign(N+1, 0);
members.assign(N+1, vi());
for(int i=1;i<=N;i++) {
p[i] = i;
members[i].push_back(i);
}
}
UnionFind() {}
int root(int u) {
return (p[u]==u)?u:p[u]=root(p[u]);
}
void merge(int i, int j) {
int b = root(i), s = root(j);
if(rank[b] < rank[s]) swap(b, s);
if(rank[b]==rank[s]) rank[b]++;
for(int i=0;i<members[s].size();i++) {
members[b].push_back(members[s][i]);
}
p[s] = b;
}
};
UnionFind UF;
pair<int, int> solve(queue<int> q1, queue<int> q2) {
//q1 has same size s q2, or 1 bigger than q2
//rebalance queues and build a and b
while(q2.size()>q1.size()) {
q1.push(q2.front()); q2.pop();
}
while(q1.size()>q2.size()+1) {
q2.push(q1.front()); q1.pop();
}
if(q1.size() == 0 || q2.size() == 0) return make_pair(-1, -1);
bool last_query = (q1.size()==1)&&(q2.size()==1);
stack<int> s1, s2;
int size_a=0, size_b=0, a[MAXN], b[MAXN];
//printf("%d %d\n", q1.size(), q2.size());
while(!q1.empty()) {
int u = q1.front(); q1.pop();
for(int i=0;i<UF.members[u].size();i++) {
a[size_a++] = UF.members[u][i];
//printf("%d ", UF.members[u][i]);
} //printf("\n");
s1.push(u);
}
//printf("===\n");
while(!q2.empty()) {
int u = q2.front(); q2.pop();
for(int i=0;i<UF.members[u].size();i++) {
b[size_b++] = UF.members[u][i];
//printf("%d ", UF.members[u][i]);
} //printf("\n");
s2.push(u);
}
//case if two representatives left
if(last_query) {
if(query(size_a, size_b, a, b)) return make_pair(s1.top(), s2.top());
else return make_pair(-1, -1);
}
//otherwise recurse
pair<int, int> ret;
if(query(size_a, size_b, a, b)) {
while(!s2.empty()) {
q2.push(s2.top()); s2.pop();
}
int siz = s1.size()/2;
while(s1.size()>siz) {
q1.push(s1.top()); s1.pop();
}
ret = solve(q1, q2);
if(ret.first != -1) return ret;
q1 = queue<int>();
while(!s1.empty()) {
q1.push(s1.top()); s1.pop();
}
ret = solve(q1, q2);
if(ret.first != -1) return ret;
} else {
while(!s1.empty()) {
q1.push(s1.top()); s1.pop();
}
ret = solve(q1, queue<int>());
if(ret.first != -1) return ret;
while(!s2.empty()) {
q2.push(s2.top()); s2.pop();
}
ret = solve(q2, queue<int>());
if(ret.first != -1) return ret;
}
//printf("===END===\n");
return make_pair(-1, -1);
}
pair<int, int> solve2(queue<int> q1, queue<int> q2) {
if(q1.size() == 0 || q2.size() == 0) return make_pair(-1, -1);
bool last_query = (q1.size()==1)&&(q2.size()==1);
stack<int> s1, s2;
int size_a=0, size_b=0, a[MAXN], b[MAXN];
//printf("%d %d\n", q1.size(), q2.size());
//printf("qq1: ");
while(!q1.empty()) {
int u = q1.front(); q1.pop();
a[size_a++] = u;
//printf("%d ", u);
s1.push(u);
}
//printf("qq2: ");
while(!q2.empty()) {
int u = q2.front(); q2.pop();
b[size_b++] = u;
//printf("%d ", u);
s2.push(u);
}
//printf("\n");
//case if two nodes left
if(last_query) {
if(query(size_a, size_b, a, b)) return make_pair(s1.top(), s2.top());
else return make_pair(-1, -1);
}
//otherwise recurse
pair<int, int> ret;
if(s1.size() > s2.size()) {
while(!s2.empty()) {
q2.push(s2.top()); s2.pop();
}
int siz = s1.size()/2;
while(s1.size()>siz) {
q1.push(s1.top()); s1.pop();
}
ret = solve2(q1, q2);
if(ret.first != -1) return ret;
q1 = queue<int>();
while(!s1.empty()) {
q1.push(s1.top()); s1.pop();
}
ret = solve2(q1, q2);
if(ret.first != -1) return ret;
} else {
while(!s1.empty()) {
q1.push(s1.top()); s1.pop();
}
int siz = s2.size()/2;
while(s2.size()>siz) {
q2.push(s2.top()); s2.pop();
}
ret = solve2(q1, q2);
if(ret.first != -1) return ret;
q2 = queue<int>();
while(!s2.empty()) {
q2.push(s2.top()); s2.pop();
}
ret = solve2(q1, q2);
if(ret.first != -1) return ret;
}
//printf("===END===\n");
return make_pair(-1, -1);
}
bool test(int x, int y) {
int a[] = {x};
int b[] = {y};
return query(1, 1, a, b);
}
int done[150][150];
void print(int N) {
//printf("TRUE EDGES:\n");
for(int i=1;i<=N;i++) {
for(int j=i+1;j<=N;j++) {
if(done[i][j] || done[j][i]) continue;
if(test(i, j)) {
done[i][j] = 1;
done[j][i] = 1;
//printf("%d %d\n", i, j);
setRoad(i, j);
return;
}
}
}
//printf("===THE END===\n");
}
void print2(int N) {
//printf("TRUE EDGES:\n");
for(int i=1;i<=N;i++) {
for(int j=i+1;j<=N;j++) {
if(done[i][j] || done[j][i]) continue;
if(test(i, j)) {
printf("TRUE:%d %d\n", i, j);
return;
}
}
}
//printf("===THE END===\n");
}
void run(int N) {
UF=UnionFind(N);
int times = N-1;
while(times--) {
//print(N);
//continue;
queue<int> q1, q2;
for(int i=1;i<=N;i++) {
if(UF.p[i] == i) {
//printf("%d ", i);
if(q1.size()>q2.size()) q2.push(i);
else q1.push(i);
}
}//printf("\n");
pair<int, int> reps = solve(q1,q2);
queue<int> qq1, qq2;
//printf("qq1: ");
for(int i=0;i<UF.members[reps.first].size();i++) {
qq1.push(UF.members[reps.first][i]);
//printf("%d ", UF.members[reps.first][i]);
} //printf("\n");
//printf("qq2: ");
for(int i=0;i<UF.members[reps.second].size();i++) {
qq2.push(UF.members[reps.second][i]);
//printf("%d ", UF.members[reps.second][i]);
} //printf("\n");
pair<int, int> ans = solve2(qq1, qq2);
UF.merge(reps.first, reps.second);
//printf("%d: reps:%d %d ans:(%d->%d)\n", q1.size()+q2.size(), reps.first, reps.second, ans.first, ans.second);
done[ans.first][ans.second] = 1;
setRoad(ans.first, ans.second);
//print2(N);
}
}
Compilation message (stderr)
icc.cpp: In member function 'void UnionFind::merge(int, int)':
icc.cpp:30:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for(int i=0;i<members[s].size();i++) {
^
icc.cpp: In function 'std::pair<int, int> solve(std::queue<int>, std::queue<int>)':
icc.cpp:60:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for(int i=0;i<UF.members[u].size();i++) {
^
icc.cpp:69:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for(int i=0;i<UF.members[u].size();i++) {
^
icc.cpp:88:24: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
while(s1.size()>siz) {
^
icc.cpp: In function 'std::pair<int, int> solve2(std::queue<int>, std::queue<int>)':
icc.cpp:152:24: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
while(s1.size()>siz) {
^
icc.cpp:170:24: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
while(s2.size()>siz) {
^
icc.cpp: In function 'void run(int)':
icc.cpp:241:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for(int i=0;i<UF.members[reps.first].size();i++) {
^
icc.cpp:246:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for(int i=0;i<UF.members[reps.second].size();i++) {
^
# | 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... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |