zoukankan      html  css  js  c++  java
  • CF1370F2The Hidden Pair(Hard Version)【交互题,二分】

    正题

    题目链接:https://www.luogu.com.cn/problem/CF1370F2


    题目大意

    \(T\)组数据,给出\(n\)个点的一棵树,有两个隐藏的关键点。你每次可以询问一个点集,交互库会回答这个点集中的一个点满足它到两个关键点的距离和最小,和这个距离。

    要求在\(11\)次询问内求出这两个关键点。

    \(1\leq T\leq 10,1\leq n\leq 1000\)


    解题思路

    首先第一下不知道干啥就问整张图吧。

    这样我们就得到了一个点\(rt\)和距离\(L\)。这个点\(rt\)一定在关键点\(u,v\)的路径上,且\(L\)表示\(u,v\)之间的距离。

    然后就好搞了,我们以\(rt\)为根,考虑利用这个\(L\)来搞点操作,我们每次选择一个深度\(dep\)然后询问所有这个深度的点的话,如果得到的距离等于\(L\)就表示这个深度有\(u\sim v\)路径上的点。

    也就是我们可以通过二分得到最深的位置,而最深的位置一定是离\(rt\)较远的一个关键点\(u\)

    而我们又知道两个关键点的距离,以\(u\)为根询问一遍深度\(L\)的节点就可以得到\(v\)了。

    二分上界是\(min\{L,dep_{max}\}\),所以次数是\(log(n)+2\leq 12\)。好像多了一次?

    再挖掘一下性质,发现我们找的是离\(rt\)较远的一个关键点,所以这段距离一定是不小于\(\lfloor\frac{L-1}{2}\rfloor\)的,这样就可以少去一次了


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int N=1100;
    struct node{
    	int to,next;
    }a[N<<1];
    int T,n,tot,ls[N],mx;
    vector<int> v[N];char s[10];
    void print(int x)
    {if(x>9)print(x/10);putchar(48+x%10);return;}
    void addl(int x,int y){
    	a[++tot].to=y;
    	a[tot].next=ls[x];
    	ls[x]=tot;return;
    }
    void dfs(int x,int fa,int dep){
    	v[dep].push_back(x);mx=max(mx,dep);
    	for(int i=ls[x];i;i=a[i].next){
    		int y=a[i].to;
    		if(y==fa)continue;
    		dfs(y,x,dep+1);
    	}
    	return;
    }
    int main()
    {
    	scanf("%d",&T);
    	while(T--){
    		memset(ls,0,sizeof(ls));tot=mx=0;
    		for(int i=0;i<=n;i++)v[i].clear();
    		scanf("%d",&n);
    		for(int i=1;i<n;i++){
    			int x,y;
    			scanf("%d%d",&x,&y);
    			addl(x,y);addl(y,x);
    		}
    		printf("? %d ",n);
    		for(int i=1;i<=n;i++)
    			print(i),putchar(' ');
    		putchar('\n');fflush(stdout);
    		int rt,L,u,uu;
    		scanf("%d%d",&rt,&L);
    		dfs(rt,0,0);u=uu=rt;
    		int l=(L-1)/2+1,r=min(L,mx);
    		while(l<=r){
    			int mid=(l+r)>>1;
    			printf("? %d ",v[mid].size());
    			for(int i=0;i<v[mid].size();i++)
    				print(v[mid][i]),putchar(' ');
    			putchar('\n');fflush(stdout);
     			int x,d;scanf("%d%d",&x,&d);
    			if(d==L)l=mid+1,u=x;
    			else r=mid-1;
    		}
    		v[L].clear();dfs(u,0,0);
    		printf("? %d ",v[L].size());
    		for(int i=0;i<v[L].size();i++)
    			print(v[L][i]),putchar(' ');
    		putchar('\n');fflush(stdout);
    		scanf("%d%d",&uu,&L);
    		printf("! %d %d\n",u,uu);fflush(stdout);
    		scanf("%s",s+1);
    	}
    }
    
  • 相关阅读:
    动画编程1
    驾照助手
    《机器学习进阶》Udacity 机器学习基础 决策树+迷你项目
    《机器学习进阶》Udacity 机器学习基础 异常值+交叉验证
    《机器学习进阶》Udacity 机器学习基础 评估指标
    《机器学习进阶》Udacity 监督学习 决策树
    《机器学习进阶》Udacity 监督学习 SVM支持向量机
    入门模拟(图形输出)——B1036.跟奥巴马一起编程( 注意行数为偶数或奇数的情况)
    入门模拟——A1036.Boys vs Girls
    leetcode 深搜广搜
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14605585.html
Copyright © 2011-2022 走看看