Rikka with Tree
众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的: 对于一棵树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时,则输出no。注意这些顶点不能全是叶子结点。
思路:单源最短路径算法。
#include <iostream>
#include <algorithm>
using namespace std;
#define MAX 9999999
#define LEN 1005
int map[LEN][LEN];
int dist[LEN];
int mark[LEN];
void init(){
int i,j;
for(i=0;i<LEN;i++){
for(j=0;j<LEN;j++){
map[i][j]=MAX;
}
}
}
void myDijstra(int n,int start){
int i,j,min,k;
for(i=1;i<=n;i++){
mark[i]=0;
dist[i]=map[start][i];
}
mark[start]=1;
dist[start]=0;
for(i=1;i<=n;i++){
min=MAX;
for(j=1;j<=n;j++){
if(!mark[j] && dist[j]<min){
min=dist[j];
k=j;
}
}
if(min==MAX)
break;
mark[k]=1;
for(j=1;j<=n;j++){
if(!mark[j] && dist[j]>dist[k]+map[k][j]){
dist[j]=dist[k]+map[k][j];
}
}
}
}
int main(){
int i,j,n,line;
int a,b,d;
while(cin>>n){
init();
line=n-1;
d=1;
for(i=0;i<line;i++){
cin>>a>>b;
if(map[a][b]>d){
map[a][b]=map[b][a]=d;
}
}
if(n<=3){
cout<<"YES"<<endl;
continue;
}
myDijstra(n,1);
// for(int i=1;i<=n;i++)
// cout<<dist[i]<<endl;
sort(dist+2,dist+n+1);
bool flag=false,flag2=true;
int tt=-100;
for(int i=2;i<n;i++){
if(dist[i]==dist[i+1]){
int tmp=dist[i];
if(flag2){
flag2=false;
tt=tmp;
}
}
}
if(tt==dist[n]||tt==-100)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}