【2020.11.30提高组模拟】删边(delete) 题解

题意简述

给一棵树删边,每次删的代价为这条边所连的两个点的子树中最大点权值。

求删光的最小代价。

\(n\le100000\).

Solution

正着思考发现没有什么好的思路,贪心的话会后效性。不妨反过来考虑

这时题目变成了:给\(n\)个点,每次连通两个点集,代价为两个点集中最大点权之和。

例如这个图

首先,每个点都是独立的。

那么你会先加入\(1-2\)还是\(2-3\)呢?

如果先加入\(2-3\),代价为\(2+3\),接下来再加入点\(1\)时,\(2-3\)所产生的贡献是\(3\)。

如果而后还有一些集合需要并进来时,当前集合所产生的贡献为\(3\),很大很浪费。

所以,我们要让点权大的点以后再合并,点权小的点先合并。

所以初始化时先把边权设为其所连两点的点权中更大的那一个。对所有边按照边权排序,再用类似并查集的方法合并同时维护集合中的最大点权。

以上。

Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
using namespace std; template<class T>inline void read(T&x)
{
char ch=getchar();
int fu;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
x*=fu;
}
inline int read()
{
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do{G[++g]=x%10;x/=10;}while(x);
for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
int n,f[100010],mx[100010],a[100010];
LL ans;
int getf(int x)
{
if(f[x]==x) return x;
return f[x]=getf(f[x]);
}
void merge(int x,int y)
{
x=getf(x);
y=getf(y);
if(x!=y)
{
ans+=mx[x]+mx[y];
mx[x]=max(mx[x],mx[y]);
f[y]=x;
}
}
struct edge
{
int x,y;
edge(int xx=0,int yy=0){x=xx,y=yy;}
// int v()const{return max(a[x],a[y]);}
bool operator<(const edge & z)const
{
return max(a[x],a[y])<max(a[z.x],a[z.y]);
}
};
vector<edge>e;
int main()
{
// freopen("delete.in","r",stdin);
// freopen("delete.out","w",stdout);
n=read();
for(int i=1;i<=n;i++) f[i]=i,mx[i]=a[i]=read();
for(int i=1;i<n;i++) e.push_back(edge(read(),read()));
sort(e.begin(),e.end());
for(unsigned i=0;i<e.size();i++)
{
merge(e[i].x,e[i].y);
}
cout<<ans;
return 0;
}

End

差点抱玲了(玲酱这么可爱为什么不抱抱呢?大雾),还好最后想到了逆向思维。

考试之后,\(\texttt{lc}\)的算法是\(O(n)\)的,让我大开眼界呢!

评测机出锅了,

仿佛回到了去年暑假的那些日子呢


不会吧不会吧,不会是个人写的都是\(O(n)\)吧!

【2020.11.30提高组模拟】删边(delete) 题解的更多相关文章

  1. 【2020.11.30提高组模拟】删边(delete)

    删边(delete) 题目 题目描述 给你一棵n个结点的树,每个结点有一个权值,删除一条边的费用为该边连接的两个子树中结点权值最大值之和.现要删除树中的所有边,删除边的顺序可以任意设定,请计算出所有方 ...

  2. 【2020.11.30提高组模拟】剪辣椒(chilli)

    剪辣椒(chilli) 题目描述 在花园里劳累了一上午之后,你决定用自己种的干辣椒奖励自己. 你有n个辣椒,这些辣椒用n-1条绳子连接在一起,任意两个辣椒通过用若干个绳子相连,即形成一棵树. 你决定分 ...

  3. JZOJ 【2020.11.30提高组模拟】剪辣椒(chilli)

    题目大意 给出一棵 \(n\) 个节点的树,删去其中两条边 使得分出的三个子树大小中最大与最小的差最小 分析 先一边 \(dfs\) 预处理出以 \(1\) 为根每个点的 \(size\) 然后按 \ ...

  4. 【2020.11.28提高组模拟】T1染色(color)

    [2020.11.28提高组模拟]T1染色(color) 题目 题目描述 给定 \(n\),你现在需要给整数 \(1\) 到 \(n\) 进行染色,使得对于所有的 \(1\leq i<j\leq ...

  5. 【2020.11.28提高组模拟】T2 序列(array)

    序列(array) 题目描述 ​给定一个长为 \(m\) 的序列 \(a\). 有一个长为 \(m\) 的序列 \(b\),需满足 \(0\leq b_i \leq n\),\(\sum_{i=1}^ ...

  6. JZOJ 6904. 【2020.11.28提高组模拟】T3 树上询问(query)

    题目 你有一棵 \(n\) 节点的树 ,回答 \(m\) 个询问,每次询问给你两个整数 \(l,r\) ,问存在多少个整数 \(k\) 使得从 \(l\) 沿着 \(l \to r\) 的简单路径走 ...

  7. 【2020.12.03提高组模拟】A组反思

    估计:40+10+0+0=50 实际:40+10+0+0=50 rank40 T1 赛时看到\(n,m\leq9\),我当机立断决定打表,暴力打了几个点之后发现在\(n\ne m\)且\(k\ne0\ ...

  8. 11.5NOIP2018提高组模拟题

    书信(letter) Description 有 n 个小朋友, 编号为 1 到 n, 他们每人写了一封信, 放到了一个信箱里, 接下来每个人从中抽取一封书信. 显然, 这样一共有 n!种拿到书信的情 ...

  9. 【2020.12.01提高组模拟】卡特兰数(catalan)

    题目 题目描述 今天,接触信息学不久的小\(A\)刚刚学习了卡特兰数. 卡特兰数的一个经典定义是,将\(n\)个数依次入栈,合法的出栈序列个数. 小\(A\)觉得这样的情况太平凡了.于是,他给出了\( ...

  10. 【2020.12.01提高组模拟】A组反思

    105,rk45 T1 赛时一开始先打了\(m=0\)的情况,也就是普通的卡特兰数,然后打了暴力,样例过了,把样例改改就不行了,原因没有保证是枚举的是合法的出栈序列 得分:\(WA\&TLE1 ...

随机推荐

  1. nuxt.js 使用 Typescript 在 VSCode 报错: File 'xxx/components/Logo.vue' is not a module. Vetur(2306)

    nuxt.js 生成的默认文件 components/Logo.vue 源码大概如下: 1 <template> 2 <svg 3 class="NuxtLogo" ...

  2. docker mysql SQLSTATE[HY000] [2002] Connection refused

    使用docker搭建lnmp环境,使用的是分容器的搭建方案 框架使用thinkphp,想要连接数据MySQL,一直显示"SQLSTATE[HY000] [2002] Connection r ...

  3. python正则表达式笔记1

    最近工作中经常用到正则表达式处理数据,慢慢发现了正则表达式的强大功能,尤其在数据处理工作中,记录下来分享给大家. 一. 正则表达式语法介绍 正则表达式(或 RE)指定了一组与之匹配的字符串:模块内的函 ...

  4. Joker 全栈低代码智能开发平台:开启高效开发新时代

    低代码开发技术凭借其独特优势,正逐渐成为软件开发领域的关键力量.Gartner 预测,到 2025 年,全球 70% 的新应用将采用低代码 / 无代码技术.Forrester 报告显示,中国低代码市场 ...

  5. 查看docker服务状态

    root用户使用 #查看docker服务状态: systemctl status docker 非root用户使用 #查看docker服务: sudo systemctl status docker

  6. docker学习 容器的启动过程

    这一节我们来稍微了解下docker原理性的东西1    docker run -i -t ubuntu /bin/bash输入上面这行命令,启动一个ubuntu容器时,到底发生了什么?大致过程可以用下 ...

  7. 全国省市区基础数据SQL插入脚本

    整理了一份全国省市区SQL插入脚本,并配上抓取数据读取插入数据库源码,附件下载地址:https://files.cnblogs.com/files/101Love/Region.rar

  8. 窗体添加按钮--java进阶day03

    1.组件.面板对象 窗体中的图片.按钮.文本都是组件,光创建出了窗体没有组件肯定不行,但是这些组件该放到窗体的哪个位置? 很明显是窗体中空白的位置,但是我们需要知道,这块空白位置在窗体中是一个被封装的 ...

  9. 构建窗体--java进阶day03

    1.窗体对象Jframe 要创建窗体就需要Jframe对象,窗体创建好不会自己显示,还需要我们自己写一段代码让其显示 2.设置窗体可见--setVisible(true) 该方法用于显示窗体 3.窗体 ...

  10. 【Linux】5.2 Shell变量

    Shell变量 1. shell变量简介 Linux Shell的变量分为,系统变量和用户自定义变量 系统变量: $HOME. $PWD. $SHELL. $USER等等 显示当前shell中所有变量 ...