题意:
给一颗树...问能否从根节点出发回到根结点..并且每条边exactly经过两次..并且遍历叶子的顺序为所给的顺序..如果可以输出遍历路径..否则输出-1
题解:
数据范围很小(N<=300)....所以就用超级暴力O(n^2)来水了...我首先将每个叶子结点的路径找出..然后暴力做LCA...相当于模拟遍历过程..并用一个计数器记录每条边访问的次数..LCA以前写过..正规的方法一定要捡起来..
Program:
#include<iostream> #include<stdio.h> #include<cmath> #include<string.h> #include<stack> #include<queue> #include<algorithm> #define oo 1000000007 #define ll long long #define MAXN 305 using namespace std; struct node { int way[MAXN],num; }L[MAXN]; vector<int> T[MAXN]; int way[MAXN],times[MAXN][MAXN],ans[2*MAXN],num,leaf; bool anc[MAXN]; void dfs(int x,int father,int n) { int i,m=T[x].size(); way[n]=x; if (x!=1 && m==1) { ++leaf; L[x].num=n; for (i=1;i<=n;i++) L[x].way[i]=way[i]; return; } for (i=0;i<m;i++) if (T[x][i]!=father) dfs(T[x][i],x,n+1); return; } bool findans() { int m,pre,x,i,t; memset(times,0,sizeof(times)); pre=1; ans[num=1]=1; while (leaf--) { scanf("%d",&x); memset(anc,false,sizeof(anc)); for (i=1;i<=L[x].num;i++) anc[L[x].way[i]]=true; for (i=L[pre].num-1;i>=1;i--) { if (times[L[pre].way[i+1]][L[pre].way[i]]>1) return false; times[L[pre].way[i+1]][L[pre].way[i]]++; ans[++num]=L[pre].way[i]; if (anc[L[pre].way[i]]) break; } if (pre==1) t=1; else t=L[pre].way[i]; for (i=1;i<=L[x].num;i++) if (L[pre].way[i]==t) break; i++; for (;i<=L[x].num;i++) { if (times[L[x].way[i-1]][L[x].way[i]]>1) return false; times[L[x].way[i-1]][L[x].way[i]]++; ans[++num]=L[x].way[i]; } pre=x; } for (i=L[x].num-1;i>=1;i--) { if (times[L[x].way[i+1]][L[x].way[i]]) return false; times[L[x].way[i+1]][L[x].way[i]]++; ans[++num]=L[x].way[i]; } return true; } int main() { int n,i; freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); scanf("%d",&n); for (i=1;i<=n;i++) T[i].clear(); for (i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); T[x].push_back(y); T[y].push_back(x); } L[1].num=L[1].way[1]=1; leaf=0; dfs(1,0,1); if (findans()) { for (i=1;i<=num;i++) printf("%d ",ans[i]); printf("\n"); } else printf("-1\n"); return 0; }