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;
}