Codeforces Round #746 (Div. 2) D. Hemose in ICPC ?(交互,dfs序)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #746 (Div. 2) D. Hemose in ICPC ?(交互,dfs序)相关的知识,希望对你有一定的参考价值。

LINK

给一棵 n n n个节点、边权未知的树

定义两个节点之间的距离为路径上所有边权的 g c d gcd gcd。每次你可以询问一个节点集合

然后交互程序会返回所给集合中最大的距离,求在不超过 12 12 12次询问的前提下

距离最大的两个节点的编号。( n < = 1 0 3 n<=10^3 n<=103)


先询问一次所有节点得到 m x mx mx

然后注意到 2 10 > = 1000 2^{10}>=1000 210>=1000,那么肯定与二分有关

我们处理出这棵树的 d f s dfs dfs

直接在 d f s dfs dfs序上二分可以找到最大值的那个点 u u u

于是输出 u u u u u u的父亲即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+10;
int n,id,topf[maxn],dfn[maxn],father[maxn],mx;
vector<int>vec[maxn];
void dfs(int u,int fa)
{
	dfn[u] = ++id; topf[id] = u; father[u] = fa;
	for(auto v:vec[u] )
	{
		if( v==fa )	continue;
		dfs( v,u );
	}
}
bool isok(int x)
{
	cout << "? " << x;
	for(int i=1;i<=x;i++)	cout << " " << topf[i];	
	cout << endl;
	int z; cin >> z;
	return z==mx;
}
int main()
{
	cin >> n;
	for(int i=1;i<n;i++)
	{
		int l,r; cin >> l >> r;
		vec[l].push_back( r ); vec[r].push_back( l );	
	}
	cout << "? " << n;
	for(int i=1;i<=n;i++)	cout << " " << i;	
	cout << endl;
	cin >> mx;	
	
	dfs( 1,0 );
	int l = 2, r = n, ans = 0;
	while( r>=l )
	{
		int mid = l+r>>1;
		if( isok(mid) )	r = mid-1, ans = mid;	
		else	l = mid+1;
	}
	cout << "! ";
	cout << topf[ans] << " " << father[topf[ans]] << endl;
}

以上是关于Codeforces Round #746 (Div. 2) D. Hemose in ICPC ?(交互,dfs序)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #746 (Div. 2)(A,B,C)

Codeforces Round #746 (Div. 2) C. Bakry and Partitioning

Codeforces Round #746 (Div. 2) 题解

Codeforces Round #746 (Div. 2)A-C

Codeforces Round #746 (Div. 2) D. Hemose in ICPC ?(交互,dfs序)

Codeforces Round #746 (Div. 2) D. Hemose in ICPC ?(交互,dfs序)