题意:给出一棵树,每个结点是黑色或者粉色。每经过一个结点一次,这个结点变一次色(一开始站在根节点时不变色)。求一条路径,沿此路径走完后整棵树变成黑色。
解:到达一个结点后需不需要往下走取决于子树中有没有粉色结点,于是先dfs一次处理子树。然后开始解,如果有粉色结点,就递归递进去。回溯在遍历完所有子树之后,如果当前节点是粉的,就走到父亲节点再走回来。注意根结点没有父亲结点,可以挑一个子节点走过去再走回来这么走两遍。
每经过一个节点变一次色,记录一下路径,这样debug的时候也方便。
其实这是道构造题吧。。。
代码:
#include <bits/stdc++.h> using namespace std; #define ll long long #define eps 0.00000001 #define inf 0x7fffffff #define maxx 200005 int n; int a[maxx]={0},son[maxx]={0}; vector<int> ans; struct edge{int u,v,next;}e[maxx*2];int head[maxx]={0};int cnt=0; void add(int u,int v){e[++cnt].u=u;e[cnt].v=v;e[cnt].next=head[u];head[u]=cnt;} void dfs2(int now,int fa){ if(son[now]==0){ a[now]=-a[now]; ans.push_back(now); return; } ans.push_back(now); a[now]=-a[now]; for(int i=head[now];i;i=e[i].next){ int to=e[i].v; if(to==fa) continue; if(a[to]==-1||son[to]>0) { dfs2(to, now); ans.push_back(now); a[now]=-a[now]; } } if(a[now]==-1&&now!=1){ ans.push_back(fa); a[fa]=-a[fa]; ans.push_back(now); a[now]=-a[now]; } } void dfs1(int now,int fa){ for(int i=head[now];i;i=e[i].next){ int to=e[i].v; if(to==fa) continue; dfs1(to,now); } if(a[now]==-1) son[fa]++; son[fa]+=son[now]; } signed main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs1(1,0); a[1]=-a[1]; dfs2(1,0); if(a[1]==-1){ int to=e[head[1]].v; ans.push_back(to); ans.push_back(1); ans.push_back(to); } for(int i:ans) printf("%d ",i); printf("\n"); return 0; }View Code