1 条题解

  • 0
    @ 2026-1-29 11:55:00

    D52 树的直径+贪心 CF911F Tree Destruction

    // 两次DFS+贪心 O(n)
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=200005;
    int h[N],idx;
    struct edge{int to,ne;}e[N<<1];
    void add(int x,int y){
      e[++idx]={y,h[x]};h[x]=idx;
    }
    int n,p,l,r,d[N],pre[N],col[N];
    long long ans;
    vector<pair<int,int>>s;
    
    void dfs(int x,int f){
      if(d[x]>d[p]) p=x;
      pre[x]=f;
      for(int i=h[x];i;i=e[i].ne){
        int y=e[i].to;
        if(y!=f){
          d[y]=d[x]+1;
          dfs(y,x);
        }
      }
    }
    void work(int x,int rt){
      for(int i=h[x];i;i=e[i].ne){
        int y=e[i].to;
        if(d[y]>d[x]) work(y,col[y]?y:rt);
        //若y在直径上,则取y
        //若y不在直径上,则取直径上的节点
      }
      if(!col[x]){ //若x不在直径上
        if(d[x]>d[x]+d[r]-d[rt]*2){
          ans+=d[x];
          s.push_back({l,x});
        }
        else{
          ans+=d[x]+d[r]-d[rt]*2;
          s.push_back({r,x});
        }
      }
    }
    int main(){
      scanf("%d",&n);
      for(int i=1,x,y;i<n;++i){
        scanf("%d%d",&x,&y);
        add(x,y); add(y,x);
      }
      dfs(1,0); l=p; d[p]=0;
      dfs(p,0); r=p;
      for(int i=r;i;i=pre[i]) col[i]=1;
      work(l,l);          //删外周
      for(;l!=r;r=pre[r]) //删直径
        ans+=d[r],s.push_back({l,r});
      printf("%lld\n",ans);
      for(auto i:s) printf("%d %d %d\n",i.first,i.second,i.second);
    }
    
    • 1

    D52 树的直径 两次DFS+贪心 [CF911F] Tree Destruction

    信息

    ID
    1841
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    7
    已通过
    3
    上传者