题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5423
题面:
3 1 2 2 3 4 1 2 2 3 1 4
YES NOHintFor the second testcase, this tree is similiar with the given tree: 4 1 2 1 4 3 4
解题:
题目意思也是蛮绕的。相似是指,两棵树顶点数相同,且每个点到根节点(1为根节点)的距离都相同。不同是指,顶点数不同或者两棵树上某个节点的父亲不一样。现要求判断一棵树是不是special,special的特征是,不存在与之相似或与之不同的树。一开始有点混,以为只要是链即可。实际上,这样会漏掉两种情况,链是不相似,且不不同的情况,应该是去找是否存在不同且相似的情况。存在输出“NO”,否则输出“YES”。
那么什么是不同且相似呢?就是某个节点它有超过1个孩子,并且它至少还可以往下两层。那么,假设当前节点在x层,其左右孩子分别为a,b,b还有孩子,那么交换a,b的孩子。对于新的到的树,就是不同且相似的,即每个节点到根节点距离不变,但交换的孩子的父亲发生了改变。
代码:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; struct edge { int next,to; }store[2010]; int head[1005],cnt; bool vis[1005]; //加一条从a到b的边 void addedge(int a,int b) { //cnt为边的存储下标 store[cnt].to=b; store[cnt].next=head[a]; //head为个顶点指向的第一条边的下标 head[a]=cnt++; } bool flag; //flag为标记,y为上一点是否有超过一个孩子的标记 void dfs(int x,bool y) { if(flag)return; //标记该点 vis[x]=1; //如果上一节点有超过一个孩子 if(y) { int num=0,tmp=head[x]; while(tmp!=-1) { //那么只要当前节点还有孩子即可 if(!vis[store[tmp].to]) { flag=true; return; } tmp=store[tmp].next; } } //如果没有,就继续向下移 else { int tmp=head[x],num=0; //数当前节点孩子数量 while(tmp!=-1) { if(!vis[store[tmp].to]) num++; tmp=store[tmp].next; } //如果孩子数量大于1 if(num>1) { int tmp=head[x]; while(tmp!=-1) { if(!vis[store[tmp].to]) dfs(store[tmp].to,1); tmp=store[tmp].next; } } //如果孩子数量小于等于1 else { int tmp=head[x]; while(tmp!=-1) { if(!vis[store[tmp].to]) dfs(store[tmp].to,0); tmp=store[tmp].next; } } } } int main() { int n,a,b; while(~scanf("%d",&n)) { memset(vis,0,sizeof(bool)*(n+1)); memset(head,-1,sizeof(int)*(n+1)); cnt=0; for(int i=1;i<n;i++) { scanf("%d%d",&a,&b); //加边 addedge(a,b); addedge(b,a); } flag=false; //数根节点孩子数量 int num=0; int x=head[1]; while(x!=-1) { num++; x=store[x].next; } if(num>1) dfs(1,1); else dfs(1,0); if(flag)printf("NO\n"); else printf("YES\n"); } return 0; }