1.樹的直徑
樹上最長的簡單路徑即為樹的直徑。
求樹的直徑的方法就是在樹上任選一點u,求距離點u最遠的點y,再求距離點y最遠的點s,點y到點s的距離即為樹的直徑。
1 #include<cstdio> 2 #include<cstring> 3 #define N 4200 4 struct hehe{ 5 int next; 6 int to; 7 }edge[N]; 8 int num_edge,head[N],dis[N],n,a,b,y; 9 int add_edge(int from,int to){ 10 edge[++num_edge].next=head[from]; 11 edge[num_edge].to=to; 12 head[from]=num_edge; 13 } 14 int dfs(int x){ 15 for(int i=head[x];i;i=edge[i].next) 16 if(!dis[edge[i].to]){ 17 dis[edge[i].to]=dis[x]+1; 18 dfs(edge[i].to); 19 } 20 } 21 int main(){ 22 scanf("%d",&n); 23 for(int i=1;i<n;++i){ 24 scanf("%d%d",&a,&b); 25 add_edge(a,b); 26 add_edge(b,a); 27 } 28 dfs(1); 29 for(int i=y=1;i<=n;i++) 30 if(dis[i]>dis[y]) 31 y=i; 32 memset(dis,0,sizeof(dis)); 33 dfs(y); 34 for(int i=y=1;i<=n;i++) 35 if(dis[i]>dis[y]) 36 y=i; 37 printf("%d",dis[y]); 38 return 0; 39 }
2.樹的重心
若有一點,其所有子樹中最大子樹的節點數最少,則該點就是這棵樹的重心。
一般的樹只有一個重心,有些有偶數個節點的樹,有兩個節點。
求樹的重心方法就是隨意確定一個根節點,先把無根樹轉化為有根樹,dfs求出所有點的子樹的節點個數。如果有一點滿足該點的子樹的節點數的二倍大於等於總結點數(size[u]*2>=n),並且該點的兒子都滿足子樹的節點數的二倍小於等於總結點數(size[son_u]*2<=n),這個點就是樹的重心。
1 #include<cstdio> 2 #define N 42000 3 int n,a,b,next[N],to[N],head[N],num,size[N],father[N],ans; 4 void add(int false_from,int false_to){ 5 next[++num]=head[false_from]; 6 to[num]=false_to; 7 head[false_from]=num; 8 } 9 void dfs(int x){ 10 size[x]=1; 11 for(int i=head[x];i;i=next[i]) 12 if(father[x]!=to[i]){ 13 father[to[i]]=x; 14 dfs(to[i]); 15 size[x]+=size[to[i]]; 16 } 17 if(size[x]*2>=n&&!ans) 18 ans=x; 19 } 20 int main(){ 21 scanf("%d",&n); 22 for(int i=1;i<n;++i){ 23 scanf("%d%d",&a,&b); 24 add(a,b); 25 add(b,a); 26 } 27 dfs(1); 28 printf("%d",ans); 29 return 0; 30 }
