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;
}
posted @ 2022-02-05 21:29  with_hope  阅读(175)  评论(0编辑  收藏  举报