CF1305D Kuroni and the Celebration

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1305D Kuroni and the Celebration相关的知识,希望对你有一定的参考价值。

CF1305D Kuroni and the Celebration

题意:

给你一棵有 n 个节点的树。对于每次询问,提交两个点,评测机会返回这两个点的 LCA。求树根。

询问格式为 ? u v,此时评测机会返回 u 和 v 的 LCA。

提交格式为 ! x,表示你得出树根为点 x。

你可以最多询问 ⌊ n 2 ⌋ \\lfloor \\frac{n}{2}\\rfloor 2n

题解:

如果一个叶子和另一个点的LCA是这个叶子,那么这个叶子一定为根
否则,这个叶子一定不是根
所以我们可以每次询问两个叶子的LCA即可,如果是其中一个点,则那个点就是根;否则删除这个两个点,有可能得到新的叶子节点,用得到的LCA去和剩下的叶子节点继续求LCA
最坏情况每次删除两个叶子节点,那么 ⌊ n 2 ⌋ \\lfloor \\frac{n}{2}\\rfloor 2n次后最多只剩下一个点,这就是根

代码:

#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{
    x= 0;
    char c= getchar();
    bool flag= 0;
    while (c < '0' || c > '9')
        flag|= (c == '-'), c= getchar();
    while (c >= '0' && c <= '9')
        x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();
    if (flag)
        x= -x;
    read(Ar...);
}
template <typename T> inline void write(T x)
{
    if (x < 0) {
        x= ~(x - 1);
        putchar('-');
    }
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}
void rd_test()
{
#ifdef ONLINE_JUDGE
#else
    startTime = clock ();
    freopen("data.in", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#else
    endTime= clock();
    printf("\\nRun Time:%lfs\\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int maxn=1020;
vector<int>vec[maxn];
int d[maxn];
int main()
{
    //rd_test();
	int n;
	read(n);
	for(int i=1;i<n;i++){
		int u,v;
		read(u,v);
		vec[u].push_back(v);
		vec[v].push_back(u);
		d[u]++;
		d[v]++;
	}
	queue<int>q;
	for(int i=1;i<=n;i++){
		if(d[i]==1)q.push(i);
	}
	int lca;
	while(!q.empty()){
//		if(q.size()==0)printf("! %d\\n",lca);
		int x=q.front();
		q.pop();
		if(q.size()==0)return printf("! %d\\n",x),0;
		int y=q.front();
		q.pop();
		printf("? %d %d\\n",x,y);
		
		cin>>lca;
		if(lca==x)return printf("! %d\\n",x),0;
		else if(lca==y)return printf("! %d\\n",y),0;
		for(auto v:vec[x])
			if((--d[v])==1)q.push(v);
		for(auto v:vec[y])
			if((--d[v])==1)q.push(v);
		
//		if(tot>n/2)break;
	}
//	cout<<lca<<endl;
    //Time_test();
}



以上是关于CF1305D Kuroni and the Celebration的主要内容,如果未能解决你的问题,请参考以下文章

CF1305E Kuroni and the Score Distribution

CF1305F Kuroni and the Punishment

cf 1305 E. Kuroni and the Score Distribution

cf 1305 E. Kuroni and the Score Distribution

CF1305F Kuroni and the Punishment (随机化)

CF1305E Kuroni and the Score Distribution(构造)