首页 > 其他分享 >CF911F-构造、树直径

CF911F-构造、树直径

时间:2024-04-09 17:14:36浏览次数:18  
标签:rt dep CF911F int back 构造 fa 直径

link:https://codeforces.com/contest/911/problem/F
给一棵树,你需要进行若干次操作:选择两个叶子,把他们的距离加入得分,删掉其中一个叶子。希望让最终得分最大。构造方案。


删叶子,距离最大,考虑树的直径
很明显用树的直径不会让答案更劣(一棵树可能有多个直径,但直径的中心是唯一的,在此基础上考虑),因此找到直径后跑一次dfs,先把非直径的点删完,再删直径上的点。

// LUOGU_RID: 154445534
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define endl '\n'
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=2e5+5;
int n,dep[N],fa[20][N];
int rt,c;
bool tag[N];
vector<vector<int>> G;
vector<tuple<int,int,int>> ans;
ll ret;
void dfs(int x){
    for(auto to:G[x])if(to!=fa[0][x]){
        dep[to]=dep[x]+1;
        fa[0][to]=x;
        if(dep[to]>dep[c])c=to;
        dfs(to);
    }
}
int jump(int x,int k){
    int t=0;
    for(;k;t++,k>>=1)if(k&1)x=fa[t][x];
    return x;
}
int LCA(int a,int b){
    if(dep[a]>dep[b])swap(a,b);
    b=jump(b,dep[b]-dep[a]);
    if(a==b)return a;
    int i=18;
    while(a!=b){
        for(;i>=0;i--)if(fa[i][a]!=fa[i][b]){
            a=fa[i][a];
            b=fa[i][b];
        }
        if(i==-1)a=b=fa[0][a];
    }
    return a;
}
int dist(int a,int b){
    return dep[a]+dep[b]-2*dep[LCA(a,b)];
}
void dfs2(int x){
    for(auto to:G[x])if(to!=fa[0][x]&&!tag[to])dfs2(to);
    for(auto to:G[x])if(to!=fa[0][x]&&tag[to])dfs2(to);
    if(x!=rt){
        if(tag[x]){
            ret+=dep[x]-dep[rt];
            ans.push_back({x,rt,x});
        }else{
            int D1=dist(x,rt),D2=dist(x,c);
            if(D1>D2){
                ret+=D1;
                ans.push_back({x,rt,x});
            }else{
                ret+=D2;
                ans.push_back({x,c,x});
            }
        }
    }
}
int main(){
    fastio;
    cin>>n;
    G=vector<vector<int>>(n+1);
    rep(i,1,n-1){
        int u,v;
        cin>>u>>v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1);
    dep[rt=c]=0;
    rep(i,1,n)fa[0][i]=0;
    dfs(c);
    //diameter will be rt->c
    rep(j,1,18)rep(i,1,n)fa[j][i]=fa[j-1][fa[j-1][i]];
    int x=c;
    while(x!=rt){
        tag[x]=true;
        x=fa[0][x];
    }
    dfs2(rt);
    cout<<ret<<endl;
    for(auto [x,y,c]:ans)cout<<x<<' '<<y<<' '<<c<<endl;
    return 0;
}

标签:rt,dep,CF911F,int,back,构造,fa,直径
From: https://www.cnblogs.com/yoshinow2001/p/18124322

相关文章

  • 3.类与对象(中篇)介绍了类的6个默认构造函数,列举了相关案例,实现了一个日期类
    1.类的6个默认成员函数如果一个类中什么成员都没有,简称为空类。空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。默认成员函数是一种特殊成员函数:​......
  • CF1943C-构造、树直径
    link:https://codeforces.com/contest/1943/problem/C题意:给一棵树,初始所有点为白色,每次操作可以选一个点\(v\),和一个距离\(d\),表示将所有距离点\(v\)恰好\(d\)的点染成黑色,问最少需要几次操作让树全黑,给出操作序列。树、二分图、黑白染色一条链怎么做?\(s_1,\dots,s_n\)......
  • Java8-类和对象、封装、构造方法
    目录类和对象类和对象的理解类的理解类的组成类和对象的关系类的定义类是由属性和行为两部分组成类的定义步骤:对象的使用创建对象的格式:调用成员的格式:练习对象内存图单个对象内存图多个对象内存图成员变量和局部变量封装思想封装概述封装代码实现private......
  • 2024年4月8日-UE5-开始菜单、事件分发器、UI预构造
    做个简单的菜单在主页面这里新建一个地图,按CTRL+N 把地面复制过来在开始关卡新建一个摄像机 打开关卡蓝图,先左键选中摄像机,然后在关卡蓝图里点右键,把摄像机拖下来   在UI里新建一个用户控件 再新建一个通用按钮 打开按钮的控件蓝图拖一个按钮进来 然......
  • 干簧管的工作原理、构造、分类和应用
    文章目录1.干簧管的工作原理2.干簧管的构造和分类2.1构造2.2分类3.干簧管的应用4.干簧管的优缺点大家好,我是记得诚。今天来聊一聊干簧管,其应用非常广泛。1.干簧管的工作原理干簧管是一个电子开关,也叫磁簧开关(ReedSwitch),是一个通过所施加的......
  • C++中的类与对象丶this指针和构造函数与析构函数 (一)
    C++中的类与对象和this指针(一)一丶类与对象1.类的引入2.类的实例化3.类的类型的大小I.计算类或对象的大小II.规定空类占一个字节大小4.类中的访问权限5.类中的构造函数和析构函数I.构造函数II.析构函数二丶this指针1.this指针的引出2.this指针的特性3.th......
  • 2024年4月7日-UE5-丰富怪物,结构体、数据表格、构造函数
    打开游戏基础文件夹,新建一个结构  打开后,新建一些变量,这里要看你的怪物用的皮肤是材质还是材质实例,选择不同的   然后再新建一个数据表格   打开怪物表填写一些怪物数据  打开怪物总类蓝图,打开构造函数ConstructionScript这个是预构造,游戏启动之前......
  • 人工智能,应该如何测试?(三)数据构造与性能测试篇
    前言人工智能场景中的性能测试与我们在互联网中创建到的有很大的不同,因为它需要模拟更复杂的情况。当然它也有相似的地方,只不过今天我们主要介绍它们不同的地方。产品分类首先我们需要澄清一下,从AI产品的类型来划分的话,我们可以分成两个大的类别:人工智能的业务类产品:AI就......
  • 18天【代码随想录算法训练营34期】● 513.找树左下角的值 ● 112. 路径总和 113.路径
    513.找树左下角的值#Definitionforabinarytreenode.#classTreeNode:#def__init__(self,val=0,left=None,right=None):#self.val=val#self.left=left#self.right=rightclassSolution:deffindBottomLeftValue(self......
  • 关于树的直径的一切
    观前须知本文使用CCBY-NC-SA4.0许可本文所有详细证明可见OIWiki笔者的博客主页正文定义树的直径指树上任意两点间距离的最大值两次DFS先以任意点为根找到最远点\(v\)再以\(v\)为根找到最远点\(u\)\(u-v\)即为该树的一条直径适用范围:无负权树证明:当\(v\)......