#交互#CF1370F2 The Hidden Pair (Hard Version)

题目


分析

考虑询问所有点可以知道两个标记点路径上的一个点,
以该点为根建树,可以二分出离该点较远的一个标记点,
再用这个标记点一次询问推出另一个,最多11次询问


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <vector>
#define rr register
using namespace std;
const int N=1011; struct node{int y,next;}e[N<<1]; char S[11];
vector<int>K[N]; int t,n,et,Top,as[N],dep[N],ans1,ans2,len;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void dfs(int x,int fa,int Dep){
	t=max(t,Dep),K[Dep].push_back(x);
	for (rr int i=as[x];i;i=e[i].next)
	    if (e[i].y!=fa) dfs(e[i].y,x,Dep+1);
}
signed main(){
	for (rr int T=iut();T;--T){
		n=iut(),et=1,Top=0;
		memset(as,0,sizeof(as));
		for (rr int i=1;i<n;++i){
			rr int x=iut(),y=iut();
			e[++et]=(node){y,as[x]},as[x]=et;
			e[++et]=(node){x,as[y]},as[y]=et;
		}
		printf("? %d",n);
		for (rr int i=1;i<=n;++i) printf(" %d",i);
		putchar(10),fflush(stdout);
		ans1=iut(),len=iut(),dfs(ans1,0,0);
		rr int l=(len-1)/2+1,r=min(len,t);
		while (l<=r){
			rr int mid=(l+r)>>1,LEN,SIZ=K[mid].size();
			printf("? %d",SIZ);
			for (rr int i=0;i<SIZ;++i) printf(" %d",K[mid][i]);
			putchar(10),fflush(stdout);
			ans2=iut(),LEN=iut();
			if (LEN==len) ans1=ans2,l=mid+1;
			    else r=mid-1;
		}
		for (rr int i=0;i<=t;++i) K[i].clear(); t=0;
		dfs(ans1,0,0);
		rr int SIZ=K[len].size();
		printf("? %d",SIZ);
		for (rr int i=0;i<SIZ;++i) printf(" %d",K[len][i]);
		putchar(10),fflush(stdout),ans2=iut(),iut();
		for (rr int i=0;i<=t;++i) K[i].clear(); t=0;
		printf("! %d %d
",ans1,ans2);
		fflush(stdout),scanf("%s",S+1);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Spare-No-Effort/p/15179417.html