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
/************************************************************************/
附上该题对应的中文题
众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的: 对于一棵树T,令F(T,i)为点1到点i的最短距离(边长是1). 两棵树A和B是相似的当且仅当他们顶点数相同且对于任意的i都有F(A,i)=F(B,i). 两棵树A和B是不同的当且仅当他们定点数不同或者存在一个i使得以1号点为根的时候i在两棵树中的父亲不同。 一棵树A是特殊的当且仅当不存在一棵和它不同的树和它相似。 现在勇太想知道一棵树到底是不是特殊的。 当然,这个问题对于萌萌哒六花来说实在是太难了,你可以帮帮她吗?
数据组数不超过100组。每组数据的第一行一个整数n(2≤n≤1000)。 接下来n−1行。每行两个整数u,v(1≤u,v≤n),代表给定树上的一条边。
对于每一组数据,如果给定树是特殊的输出"YES"否则输出"NO"。
3 1 2 2 3 4 1 2 2 3 1 4
YES NO
对于第二组数据下面这棵树和它相似。 4 1 2 1 4 3 4
出题人的解题思路:
显然一棵树是独特的当且仅当任意处于每一个深度的点数是"1 1 1 1 ... 1 1 x"。所以直接DFS一下求出每一个点到根的距离然后判断一下就好了 。
对于此题,就是让我们判断给定的树是不是特殊的树,根据题目的定义,一棵树A是特殊的当且仅当不存在一棵和它不同的树和它相似,简而言之,就是对于给定的树,不存在那么一棵树,满足[结点数相同,F(A,i)=F(B,i),且以1号点为根的时候i在两棵树中的父亲不同 ]像这种中间层(除根与叶子层)结点超过1个的树,都不是特殊的树,因为只要变换其叶子结点的位置,就能找到一个满足[结点数相同,F(A,i)=F(B,i),且以1号点为根的时候i在两棵树中的父亲不同]的树
所以,我们只需用bfs或dfs判断除叶子层外是不是每一层都只有一个结点即可
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<stack> #include<math.h> #include<vector> #include<map> #include<set> #include<stdlib.h> #include<cmath> #include<string> #include<algorithm> #include<iostream> #define exp 1e-10 using namespace std; const int N = 1001; const int inf = 1000000000; const int mod = 2009; vector<int> s[N]; int ans[N],v[N]; void bfs(int n) { queue<int> q; q.push(n); v[n]=1; while(!q.empty()) { int t=q.front(); q.pop(); for(int i=0;i<s[t].size();i++) if(!v[s[t][i]]) { q.push(s[t][i]); v[s[t][i]]=v[t]+1; } } } int main() { int n,i,a,b,Max; while(~scanf("%d",&n)) { memset(ans,0,sizeof(ans)); memset(v,0,sizeof(v)); for(i=1;i<=n;i++) s[i].clear(); for(i=1;i<n;i++) { scanf("%d%d",&a,&b); s[a].push_back(b); s[b].push_back(a); } bfs(1); for(Max=0,i=1;i<=n;i++) { ans[v[i]]++; Max=max(Max,v[i]); } for(i=1;i<Max;i++) { //printf("%d\n",ans[i]); if(ans[i]!=1) break; } if(i!=Max) puts("NO"); else puts("YES"); } return 0; }菜鸟成长记