n(n<=100)个点的树,读入树后,
你需要给n-1条边用最小的颜色数染色,
输出染色数k和具体每条边的染色方案
然后,每一轮,你先读入一个交互系统给出的数(1/-1/0):
1表示你已经走到根了,获胜,游戏结束
-1表示你之前的操作非法了,相当于程序wa了
0表示你当前在某个非根的点,
以下读入k个数,代表当前节点连的所有边中,
颜色为1,为2,...,为k的边的条数各有多少个
每次,你只能选择一个边的条数为1的颜色(因为你只能选择颜色,且交互系统会从颜色里随机抽一条边)
走这条边,走到父亲节点,不断和交互机交互,
每次输出你每次选的颜色,完成后续交互过程,直至当前点为根后读入1结束
灵茶山艾府群
分三种情况讨论,看到题解后,发现这个讨论还是挺自然的,但是自己手玩就玩不出来
首先,原则肯定是,我们只要能对于深度不同的点能有所区分即可,深度相同的点染一样的无所谓
1. 菊花图:即所有点都连的是根,此时只需要一种颜色,一步就走到根
2. 不难发现,我们需要让连接到父亲的边的颜色,在u这个点连接的所有边的颜色中唯一
所以,只要深度>=2了,肯定需要至少两种颜色,
那两种颜色行不行呢,考虑一条长为4的链1-2-3-4,1为根
如果点2的染色方案是1、2,点3的染色方案是2、1的话,
按照交互机的读入方式,无法区分这两个点,也就无法决定,收到这个读入后该走颜色1还是颜色2
所以,对于所有度为2的点,尝试去用相同的方式染(比如连接父亲的染成颜色1,另一端染成颜色2),类似二分图判定的过程
如果这种染边方式全局不冲突,则一定可以用两种颜色染,否则至少需要三种
附一个网友给的很强的样例,用以说明这个染色的过程,1、2并不需要同层
对每个2度点染1、2,将根这个点删掉之后,考虑每个连通块独立考虑合法性
没有2度点的连通块,两种颜色循环染色即可
3. 三种的时候,就一定可以解决所有情况了,三种颜色循环染色即可
不妨第一层染1、2,第二层2、3,第三层3、1,以此类推,就可以循环下去了
#include
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair P;
#define fi first
#define se second
#define dbg(x) cerr<<(#x)<<":"< dist(l, r); return dist(gen); }
const int N=105;
int n,p[N],k,c[N],d[N];
vectore[N],f[N];
bool vis[N];
bool dfs(int u,int w){
if(~c[u] && c[u]!=w)return 0;
if(vis[u])return 1;
c[u]=w;
vis[u]=1;
for(auto &v:f[u]){
if(v==1)continue;
if(!dfs(v,w^1)){
return 0;
}
}
return 1;
}
void dfs2(int u,int w){
c[u]=w;
for(auto &v:e[u]){
dfs2(v,(w+1)%3);
}
}
bool one(){
k=1;
return SZ(f[1])==n-1;
}
bool two(){
k=2;
memset(c,-1,sizeof c);
rep(u,2,n){
if(SZ(f[u])==2 && !dfs(u,0)){
return 0;
}
}
rep(u,2,n){
if(!vis[u])dfs(u,0);
}
return 1;
}
bool three(){
k=3;
dfs2(1,0);
return 1;
}
void out(){
pte(k);
rep(i,2,n){
printf("%d%c",1+c[i]," \n"[i==n]);
}
fflush(stdout);
}
void walk(){
int v;
while(sci(v) && !v){
vectorp;
rep(i,1,k){
sci(d[i]);
if(d[i]==1)p.pb(i);
}
if(SZ(p)==1)pte(p[0]);
else pte(p[0]==1 && p[1]==3?p[1]:p[0]);//12,23,31
fflush(stdout);
}
}
bool sol(){
sci(n);
rep(i,2,n){
sci(p[i]);
e[p[i]].pb(i);
f[i].pb(p[i]);
f[p[i]].pb(i);
}
if(one())return 1;
if(two())return 1;
return three();
}
int main(){
sol();
out();
walk();
return 0;
}