CF1879E Interactive Game with Coloring
被坑惨了。珍爱生命,远离构造。
Description
这是一道交互题。
你在和交互库玩这样一个游戏。给你一棵
设起点到根节点的距离为
现请你在保证能够获胜的前提下,用 最小的颜色数 对边染色,并给出方案。随后交互库与你进行上述游戏,你要对每一步给出应该选择的边直至获胜。
交互库自适应,
Solution
发现题意本质是构造方案,使在任意位置给出每种颜色的边数,都能唯一确定通向根的那条边。
因为如果选择某种颜色的边,且这样的边不止一条,会由交互库来选择,所以通向根的边不能与其他边颜色相同。而连向儿子的边不属于同一棵子树,它们之间选什么颜色都互不影响。为了方便地判断根所在的边,我们希望连向儿子的颜色都相同。
那么设
先不考虑该问题,我们只需要两种颜色,
考虑奇偶性不同的情况,发现此时它们连向父亲的边不是同一个颜色,无法区分。这里考虑引入第三种颜色。从根节点向下依次染色,对于非特殊点,只需保证父亲的边和儿子的边不同色即可;对于特殊点,我们钦定:若连向父亲的边颜色为
看起来很对?Wrong answer on test 4.
点
完全没想到这点,鉴定为菜。
const int N=105;
int n,fa[N];
vector<int> e[N];
int son[N],dep[N],mx;
void dfs(int u)
{
dep[u]=dep[fa[u]]+1; mx=max(mx,dep[u]);
for(auto v:e[u]) dfs(v);
}
int flag[2],col[N];
namespace sub3
{
int x[N];
void dfs(int u)
{
for(auto v:e[u])
{
if(son[u]==1) col[v]=((col[u]+1)>3)?1:col[u]+1;
else {for(int j=1;j<=3;j++) if(j!=col[u]) {col[v]=j;break;}}
dfs(v);
}
}
void solve()
{
for(auto v:e[1]) col[v]=1;
for(auto v:e[1]) dfs(v);
cout<<3<<endl;for(int i=2;i<=n;i++) cout<<col[i]<<" ";cout<<endl;
// assert(false);
while("qwq")
{
int op=read();
if(op==1) return;
assert(op!=-1);
static int cnt[5]; int sum=0;
for(int i=1;i<=3;i++) cnt[i]=read(),sum+=cnt[i];
if(sum==2)
{
if(cnt[1]&&cnt[3]) cout<<3<<endl;
else if(cnt[1]) cout<<1<<endl;
else cout<<2<<endl;
}
else for(int i=1;i<=3;i++) if(cnt[i]==1) {cout<<i<<endl;break;}
}
}
}
namespace sub2
{
int x[N],ff;
void dfs(int u)
{
for(auto v:e[u])
{
for(int j=1;j<=2;j++) if(j!=col[u]) {col[v]=j;break;}
if(son[u]==1&&u!=1) ff=col[u];
dfs(v);
}
}
void solve()
{
for(auto v:e[1]) dfs(v);
cout<<2<<endl;for(int i=2;i<=n;i++) cout<<col[i]<<" ";cout<<endl;
while("qwq")
{
int op=read();
if(op==1) return;
assert(op!=-1);
static int cnt[5]; int sum=0;
for(int i=1;i<=2;i++) cnt[i]=read(),sum+=cnt[i];
if(sum==2) cout<<ff<<endl;
else for(int i=1;i<=2;i++) if(cnt[i]==1) {cout<<i<<endl;break;}
}
}
}
void check(int u)
{
if(son[u]==1) flag[dep[u]%2]=1;
for(auto v:e[u]) check(v);
}
int main()
{
n=read();
for(int i=2;i<=n;i++) fa[i]=read(),e[fa[i]].push_back(i),son[fa[i]]++;
dfs(1);
if(mx==2)
{
cout<<1<<endl;
for(int i=2;i<=n;i++) cout<<1<<" ";
cout<<endl;
int op=read(); for(int i=1;i<=1;i++) int x=read();
cout<<1<<endl,op=read(); return 0;
}
int qwq=0;
for(auto v:e[1])
{
flag[0]=flag[1]=0;
check(v);
if(flag[0]&&flag[1]) {sub3::solve();return 0;}
col[v]=flag[1]?2:1;
}
sub2::solve();
return 0;
}