题目大意
给定一颗n个节点的树,n<=10^5
每个节点有一个颜色, 黑色或白色。
你需要输出一条从节点1开始行走的,长度不超过10^7的路径,规定每走到一个节点就会改变其颜色(注意初始站在1不会改变1的颜色),每次只能走向相邻的节点,你输出的路径需要使所有结点都变成黑色。
构造一波
我们用solve(x)表示从x开始走,最后回到x,任务是将以x为根的子树中除了x以外的节点都变成黑色(x的颜色可以任意)。
具体呢,先往每个子树走,走回来后,如果x一个儿子y是白色,就从x走到y再走回x把y变黑。最后退出。
这样做一遍后,除了1以外都是黑色,然后如果1是白色,找到一个1的儿子(一定是黑色),走过去走回来再走过去然后结束路径。
这样就全黑了。然后路径长度也不会很大。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=200000+10;
int h[maxn],go[maxn*2],next[maxn*2],a[maxn];
int ans[10000000+10],sta[100];
int i,j,k,l,t,n,m,top,tot,cnt;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
void add(int x,int y){
go[++tot]=y;
next[tot]=h[x];
h[x]=tot;
}
void solve(int x,int y){
int t=h[x];
while (t){
if (go[t]!=y){
ans[++top]=go[t];
a[go[t]]=-a[go[t]];
solve(go[t],x);
ans[++top]=x;
a[x]=-a[x];
if (a[go[t]]==-1){
ans[++top]=go[t];
a[go[t]]=1;
ans[++top]=x;
a[x]=-a[x];
}
}
t=next[t];
}
}
void write(int x){
if (!x){
putchar('0');
putchar(' ');
return;
}
cnt=0;
while (x){
sta[++cnt]=x%10;
x/=10;
}
while (cnt) putchar(sta[cnt--]+'0');
putchar(' ');
}
int main(){
n=read();
fo(i,1,n) a[i]=read();
fo(i,1,n-1){
j=read();k=read();
add(j,k);add(k,j);
}
ans[top=1]=1;
//dfs(1,0);
solve(1,0);
if (a[1]==-1){
t=go[h[1]];
ans[++top]=t;
ans[++top]=1;
ans[++top]=t;
}
fo(i,1,top) write(ans[i]);
}