AtCoder Beginner Contest 398-e

原题链接

这道题是一道交互题,他让我们实现一个程序来赢得这个游戏。因为输入是不确定的,所以我们要考虑必胜的策略。我们发现输入会导致出现一些满足条件的偶数环,但我们不考虑这些未知情况,只考虑初始的树中有几种已知情况满足条件,所以我们可以通过预处理来算出有几对点满足题目要求,如果有奇数对点满足要求,则输出\(First\)(因为有奇数对点,所以如果我们想拿到最后一对点,我们必须先手才行),否则输出\(Second\)(因为有偶数对点,所以如果我们想拿到最后一对点,我们必须后手才行)。然后我们就要根据先手后手来进行输入和输出,并用一个\(bool\)数组来维护两个点之间是否有边相连,输出时找到第一个满足条件且没有相连的边进行输出,最后遇到\(-1 -1\)时记得结束程序。

细节

每次输出后记得刷新缓存区(\(fflush(stdout)\)

#include<iostream>
#include<vector>
using namespace std;
int n;
int fa[110],siz[110],son[110],dep[110],top[110]; //LCA
vector<int> vec[110]; //存储每个节点有哪些子节点
vector<pair<int,int> > hf; //存储满足题目要求的点对的集合
bool f[110][110]; //标记两个点之间是否有边相连

void dfs1(int u,int ff)
{
	fa[u]=ff;
	siz[u]=1;
	dep[u]=dep[ff]+1;
	for(auto v:vec[u])
	{
		if(v==ff) continue;
		dfs1(v,u);
		siz[u]+=siz[v];
		if(siz[v]>siz[son[u]]) son[u]=v;
	}
}

void dfs2(int u,int t)
{
	top[u]=t;
	if(!son[u]) return;
	dfs2(son[u],t);
	for(auto v:vec[u])
	{
		if(v==fa[u] || v==son[u]) continue;
		dfs2(v,v);
	}
}

int lc(int u,int v)
{
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		u=fa[top[u]];
	}
	if(dep[u]<dep[v]) swap(u,v);
	return v;
}

int main()
{
	cin>>n;
	int u,v;
	for(int i=1;i<n;i++)
	{
		cin>>u>>v;
		vec[u].push_back(v);
		vec[v].push_back(u);
		f[u][v]=f[v][u]=true;
	}
	dfs1(1,0);
	dfs2(1,1); //树链剖分
	for(int i=1;i<=n;i++) 
	{
		for(int j=i+1;j<=n;j++) 
		{
			int la=lc(i,j); //求LCA
			if(!f[i][j] && (dep[i]+dep[j]-dep[la]-dep[fa[la]])%2==0) hf.push_back(make_pair(i,j)); //判断是否是奇数环,若不是将这对点加入集合中
		}
	}
	int tp;
	if(hf.size()&1) cout<<"First"<<"\n",tp=1;
	else cout<<"Second"<<"\n",tp=2; //判断First还是Second
	fflush(stdout); //刷新缓存区
	while(true)
	{
		if(tp==1)
		{
			while(f[hf.back().first][hf.back().second]) hf.pop_back();
			f[hf.back().first][hf.back().second]=f[hf.back().second][hf.back().first]=true;
			cout<<hf.back().first<<' '<<hf.back().second<<"\n"; //输出
			fflush(stdout);
			cin>>u>>v; //输入
			if(u==-1 && v==-1) return 0; //赢了
			f[u][v]=f[v][u]=true; //标记
		}
		else
		{
			cin>>u>>v; //输入
			if(u==-1 && v==-1) return 0; //赢了
			f[u][v]=f[v][u]=true; //标记
			while(f[hf.back().first][hf.back().second]) hf.pop_back();
			f[hf.back().first][hf.back().second]=f[hf.back().second][hf.back().first]=true;
			cout<<hf.back().first<<' '<<hf.back().second<<"\n"; //输出
			fflush(stdout);
		}
	}
	return 0;
}
posted @ 2025-03-23 11:25  CMY2013  阅读(18)  评论(0)    收藏  举报