LOJ #6797. 「ICPC World Finals 2020」QC QC 题解
题目链接:#6797. 「ICPC World Finals 2020」QC QC
题目大意:有 \(n\) 个人,严格半数以上诚实,你可以进行不超过 \(12\) 次操作,每一次给一个序列 \(\{p\}\) 表示向 \(i\) 询问 \(p_i\) 是否诚实,\(n\leq 100\)。
题解:随机问,通过分类讨论可以得到若干个必定相同的连通块,每次尽可能多决策,在 \(12\) 次之内合并得只剩两个的概率挺大的,正确性不会分析,时间复杂度 \(O(n^2\log n)\)。
代码:
#include <random>
#include <cstdio>
#include <vector>
#include <algorithm>
const int Maxn=100;
int n;
namespace DSU{
int fa[Maxn+5],sz[Maxn+5];
void init(){
for(int i=1;i<=n;i++){
fa[i]=i;
sz[i]=1;
}
}
int find(int x){
if(x==fa[x]){
return x;
}
return fa[x]=find(fa[x]);
}
void merge(int x,int y){
int fa_x=find(x),fa_y=find(y);
if(fa_x==fa_y){
return;
}
fa[fa_y]=fa_x;
sz[fa_x]+=sz[fa_y];
}
}
std::vector<std::pair<int,int> > lis;
bool vis[Maxn+5][Maxn+5];
int mat[Maxn+5];
void solve(){
scanf("%d",&n);
DSU::init();
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
vis[i][j]=0;
}
}
for(int t=1;t<=12;t++){
lis.clear();
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(DSU::find(i)!=DSU::find(j)){
lis.push_back(std::make_pair(i,j));
}
}
mat[i]=-1;
}
std::sort(lis.begin(),lis.end(),[&](std::pair<int,int> u,std::pair<int,int> v){
return std::max(DSU::sz[DSU::find(u.first)],DSU::sz[DSU::find(u.second)])>std::max(DSU::sz[DSU::find(v.first)],DSU::sz[DSU::find(v.second)]);
});
for(std::pair<int,int> i:lis){
if(vis[DSU::find(i.first)][DSU::find(i.second)]){
continue;
}
if(mat[i.first]==-1&&mat[i.second]==-1){
mat[i.first]=i.second;
mat[i.second]=i.first;
}
}
for(int i=1;i<=n;i++){
if(mat[i]==-1){
mat[i]=i;
}
}
printf("test");
for(int i=1;i<=n;i++){
printf(" %d",mat[i]);
}
puts("");
fflush(stdout);
static char s[Maxn+5];
scanf("%s",s+1);
for(int i=1;i<=n;i++){
if(i<mat[i]){
if(s[i]=='1'&&s[mat[i]]=='1'){
DSU::merge(i,mat[i]);
}
else{
vis[DSU::find(i)][DSU::find(mat[i])]=1;
vis[DSU::find(mat[i])][DSU::find(i)]=1;
}
}
}
}
int max_v=0;
for(int i=1;i<=n;i++){
if(DSU::find(i)==i){
max_v=std::max(max_v,DSU::sz[DSU::find(i)]);
}
}
printf("answer ");
for(int i=1;i<=n;i++){
printf("%d",DSU::sz[DSU::find(i)]==max_v);
}
puts("");
fflush(stdout);
}
int main(){
int T;
scanf("%d",&T);
while(T--){
solve();
}
return 0;
}
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。