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;
}