[关闭]
@Acqua 2019-01-26T09:53:38.000000Z 字数 5774 阅读 1374

树的直径与重心(Jan. 22th, 2019)

模型 未完成

树的直径

定义:树上的最长简单路。
说明:因为树上两点间简单路唯一,所以记树上两点间简单路为
求法:,第一次找出离根最远的点,记为;第二次找出离最远的点,这两点就是直径的端点[1]
性质:
1. 对于树的直径都是叶子结点(广义上的叶子结点是度为的结点,即对于广义叶子结点,除非树上结点作为根节点,都有点为狭义叶子结点)[2]
2. 对于树上任一结点,与其距离最远的结点一定在直径端点上[3]
3. 对于直径为的树和直径为的树,两树合并后的直径[4]
4. 若一棵树存在多条直径,那么这些直径交于一点且交点是这些直径的中点[5]
5. 对于一棵树,如果在一个点的上接一个叶子节点,那么最多会改变直径端点集中的一个端点[6]

代码:

  1. // La Pluie
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. using namespace std;
  7. const int N=4e4+5;
  8. struct edge{
  9. int v,w,next;
  10. } e[N<<1];
  11. int n,m,head[N],root,ans,k=1;
  12. void adde(int u,int v,int w){
  13. e[k]=(edge){v,w,head[u]};
  14. head[u]=k++;
  15. }
  16. void dfs(int u,int f,int s){
  17. if(s>ans) root=u,ans=s;
  18. for(int i=head[u];i!=-1;i=e[i].next){
  19. int v=e[i].v,w=e[i].w;
  20. if(v==f) continue;
  21. dfs(v,u,s+w);
  22. }
  23. }
  24. int main(){
  25. memset(head,-1,sizeof(head));
  26. scanf("%d%d",&n,&m);
  27. for(int i=1;i<=m;i++){
  28. int u,v,w;char c;
  29. scanf("\n%d %d %d %c",&u,&v,&w,&c);
  30. adde(u,v,w);adde(v,u,w);
  31. }
  32. dfs(1,0,0);dfs(root,0,0);
  33. printf("%d",ans);
  34. return 0;
  35. }

树的重心

定义:树上的一个点,去掉后能使得到的森林中结点数最多的树结点数最少。
求法:记以为根的子树中结点数为(不包含),则。统计最小的,将加入答案数组(注意:树的重心一般不止一个)。
代码:

  1. // La Pluie
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. using namespace std;
  7. const int N=5e4+5;
  8. struct edge{
  9. int v,next;
  10. }e[N<<1];
  11. int head[N],size[N],k=1,ans=1e9,res[N],t,n;
  12. void adde(int u,int v){
  13. e[k]=(edge){v,head[u]};
  14. head[u]=k++;
  15. }
  16. void dfs(int u,int f){
  17. int son=0;
  18. for(int i=head[u];i!=-1;i=e[i].next){
  19. int v=e[i].v;
  20. if(v==f) continue;
  21. dfs(v,u);
  22. son=max(son,size[v]);
  23. size[u]+=size[v];
  24. }
  25. int tmp=max(son,n-size[u]-1);
  26. if(ans>tmp){
  27. ans=tmp;
  28. t=0;
  29. res[++t]=u;
  30. }
  31. else if(ans==tmp) res[++t]=u;
  32. size[u]++;
  33. }
  34. int main(){
  35. memset(head,-1,sizeof(head));
  36. scanf("%d",&n);
  37. for(int i=1;i<n;i++){
  38. int u,v;
  39. scanf("%d%d",&u,&v);
  40. adde(u,v);adde(v,u);
  41. }
  42. dfs(1,0);
  43. sort(res+1,res+t+1);
  44. for(int i=1;i<=t;i++){
  45. printf("%d ",res[i]);
  46. }
  47. return 0;
  48. }

[1]
[2]










[3]





















[4]




























[5]

[6]

1. u\in D。设u为u_1。
\because (u,u_2)为该树直径,
\therefore
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注