• CF-911F. Tree Destruction(树的直径)


    CF传送门

    洛谷传送门


    解题思路

    题目中有几个需要注意的翻译得不是很好的点:

    • 无根树
    • 最后还需要输出每次选取和删除的点

    我们回顾一下树的直径dfs求法,可知树上到任意一个点距离最远的点一定是树的直径的一个端点。所以我们可以选取树的直径的某个端点作为整棵树的根,然后对于每个叶子节点:

    • 若不在直径上,比较一下到两个直径端点哪个更远,取更远的那个
    • 若是直径上的点,为了保护直径,我们先不处理,最后单独处理直径(一条链,对答案的总贡献为l*(l+1)/2,l为直径长度)

    注意最后输出的时候一定要按照顺序(从叶子节点出发)。

    AC代码

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cmath>
     4 #include<cstdio>
     5 #include<cstring>
     6 using namespace std;
     7 const int maxn=200005;
     8 int p[maxn],dis[maxn],dep[maxn],fa[maxn],vis[maxn],anss[maxn];
     9 int n,cnt,maxd,rt1,rt2;
    10 long long ans,l;
    11 struct node{
    12     int v,next;
    13 }e[maxn*2];
    14 void insert(int u,int v){
    15     cnt++;
    16     e[cnt].v=v;
    17     e[cnt].next=p[u];
    18     p[u]=cnt;
    19 } 
    20 void dfs(int u,int f){
    21     for(int i=p[u];i!=-1;i=e[i].next){
    22         if(e[i].v==f) continue;
    23         fa[e[i].v]=u;
    24         dep[e[i].v]=dep[u]+1;
    25         if(dep[e[i].v]>dep[maxd]) maxd=e[i].v;
    26         dfs(e[i].v,u);
    27     }
    28 }
    29 void dfs2(int u,int f){
    30     for(int i=p[u];i!=-1;i=e[i].next){
    31         if(e[i].v==f) continue;
    32         dis[e[i].v]=dis[u]+1;
    33         dfs2(e[i].v,u);
    34     }
    35 }
    36 void dfs3(int u,int f){
    37     for(int i=p[u];i!=-1;i=e[i].next){
    38         if(e[i].v==f) continue;
    39         dfs3(e[i].v,u);
    40     }
    41     if(!vis[u]) printf("%d %d %d
    ",u,anss[u],u);
    42 }
    43 int main()
    44 {
    45     memset(p,-1,sizeof(p));
    46     scanf("%d",&n);
    47     for(int i=1;i<n;i++){
    48         int u,v;
    49         scanf("%d%d",&u,&v);
    50         insert(u,v);
    51         insert(v,u);
    52     }
    53     dfs(1,-1);
    54     dep[maxd]=0;
    55     rt1=maxd;
    56     fa[maxd]=-1;
    57     dfs(maxd,-1);
    58     rt2=maxd;
    59     l=dep[rt2];
    60     for(int i=rt2;i!=-1;i=fa[i]) vis[i]=1;
    61     dfs2(rt2,-1);
    62     for(int i=1;i<=n;i++){
    63         if(vis[i]==0){
    64             if(dep[i]>dis[i]){
    65                 anss[i]=rt1;
    66                 ans+=dep[i];
    67             }else{
    68                 anss[i]=rt2;
    69                 ans+=dis[i];
    70             }
    71         }
    72     }
    73     ans+=(l+1)*l/2;
    74     printf("%lld
    ",ans);
    75     dfs3(rt1,-1);
    76     for(int i=rt2;i!=rt1;i=fa[i]) printf("%d %d %d
    ",i,rt1,i);
    77     return 0;
    78 }
  • 相关阅读:
    排序题目
    力扣二分法题目
    力扣动态相似题目
    875爱吃香蕉的珂珂
    410分割数组的最大值
    1335工作计划的最低难度
    287寻找重复数
    69X的平方根
    力扣相似题目
    解决Linux虚拟机内 /mnt/hgfs路径下文件为空问题
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/14698757.html
Copyright © 2020-2023  润新知