CF1120D Power Tree
题意简述
给你一棵有根树,定义叶子为度数为1的点。
你可以以$ w_x \(的代价控制\)x\(点。选择控制之后可以给它的子树里的叶子加
上\)t (t \in Z )$。
你要以最小的总代价使得:另一个人在叶子上任意放数,你都可以把它
们都变成0。
最后输出最小的总代价,以及有多少点可能被控制,以及每个可能被控制的点的编号
思路索引
首先,我们可以把所有的叶子节点按照 dfs序 抽象成一个序列
接下来,我们可以很神奇的发现,每一个点就对应着一个区间这不是废话吗
然后,选择某个区间后,我们就可以对它进行区间加的操作
既然是区间操作,肯定是不方便的,然后就很自然的想到了差分哪里自然了
若点\(x\)对应区间\([l,r]\),那么,我们控制点x,就等同于在\(l\)处\(+t\),在\(r+1\)处\(-t\)(因此,我们需要虚构出一个新的叶子节点,以保证不会爆掉)
我们观察一下这个序列,发现如果原数组均为0,则差分数组也均为0
所以说,我们可以在\(l\)到\(r+1\)之间连一条边权为\(w_x\)的边,我们可以在这条边的一端加上一个数,而在另一端减去一个相同的数
我们发现,若所有叶子都联通,那么因为差分数组的和为0,所以我们必然能将每一个点都变成0
求一遍最小生成树即可
代码实现
//```
#include<bits/stdc++.h>
#define ll long long
#define now edge[i].v
#define rep(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
const int SZ=2e5+7;
ll ans;
int cnt;
int L,R;
int u,v;
int n,T;
int w[SZ];
int fa[SZ];
int sz[SZ];
bool vis[SZ];
int head[SZ];
bool f[SZ];
int l[SZ],r[SZ];
struct wxp{
int v,nxt;
}edge[SZ<<1];
struct pb{
int u,v,w,o;
}E[SZ];
bool cmp(pb p1,pb p2){
return p1.w<p2.w;
}
int getfa(int x){
return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
void add(int u,int v){
edge[++cnt]=(wxp){v,head[u]};
head[u]=cnt;
}
void dfs(int x){
sz[x]=1;
vis[x]=1;
for(int i=head[x];i;i=edge[i].nxt)
if(!vis[now]){
dfs(now);
sz[x]+=sz[now];
l[x]=min(l[x],l[now]);
r[x]=max(r[x],r[now]);
}
if(sz[x]==1) l[x]=r[x]=++T;
E[x]=(pb){l[x],r[x]+1,w[x],x};
}
int main(){
scanf("%d",&n);
rep(i,1,n) scanf("%d",&w[i]);
rep(i,1,n-1){
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
memset(l,0x3f,sizeof(l));
dfs(1);
sort(E+1,E+n+1,cmp);
rep(i,1,T+1) fa[i]=i;
int sum=0;
for(L=1;L<=n;L=R+1){
R=L;
while(E[R+1].w==E[L].w&&R<n) R++;
rep(i,L,R){
u=E[i].u,v=E[i].v;
if(getfa(u)!=getfa(v)) f[E[i].o]=1,sum++;
}
rep(i,L,R){
u=E[i].u,v=E[i].v;
if(getfa(u)!=getfa(v)){
ans+=1ll*E[i].w;
fa[fa[u]]=fa[v];
}
}
}
printf("%I64d %d\n",ans,sum);
rep(i,1,n) if(f[i]) printf("%d ",i);
}
CF1120D Power Tree的更多相关文章
- CF1120D Power Tree(构造题,差分,最小生成树)
很有趣的一道题. 首先可以对每个叶子进行编号.按照DFS到的顺序即可.(假设从 $1$ 到 $k$) 然后对每个点求出它管辖的所有叶子的编号.因为是DFS序所以这一定是个区间.设点 $u$ 的这个区间 ...
- Codeforces 1120D Power Tree [最小生成树]
洛谷 Codeforces 这题怎么一个中文题解都没有,是不是你们都认为太水了-- 思路 显然可以用dfs序把每个节点变成给一个区间的叶子节点加上某个数. 显然把叶子序列差分一下变为\(a_1,a_2 ...
- [CF607D]Power Tree
题目大意: 一棵树初始只有一个编号为$1$的权值为$w_1$的根.$q(q\le2\times10^5)$次操作,每次可以给出$v,w(w<10^9)$,新建一个结点作为$v$的子结点,权值为$ ...
- Solution -「树上杂题?」专练
主要是记录思路,不要被刚开始错误方向带偏了 www 「CF1110F」Nearest Leaf 特殊性质:先序遍历即为 \(1 \to n\),可得出:叶子节点编号递增或可在不改变树形态的基础上调整为 ...
- cf Round 607
A.Chain Reaction(DP+二分) 题意:一排有n个灯塔,每个灯塔给出坐标xi和力量yi,每次从最右边依次点亮灯塔,每点亮一个灯塔,它左边的距离它yi范围内的灯塔将受到损坏.现在允许在最右 ...
- codeforces选做
收录了最近本人完成的一部分codeforces习题,不定期更新 codeforces 1132E Knapsack 注意到如果只使用某一种物品,那么这八种物品可以达到的最小相同重量为\(840\) 故 ...
- Codeforces Round #543 Div1题解(并不全)
Codeforces Round #543 Div1题解 Codeforces A. Diana and Liana 给定一个长度为\(m\)的序列,你可以从中删去不超过\(m-n*k\)个元素,剩下 ...
- Codeforces Round #539Ȟȟȡ (Div. 1) 简要题解
Codeforces Round #539 (Div. 1) A. Sasha and a Bit of Relax description 给一个序列\(a_i\),求有多少长度为偶数的区间\([l ...
- ZOJ 3684 Destroy 树的中心
中心节点就是树的中心,2遍dfs求到树的直径.而中心一定在直径上,顺着直径找到中心就够了. 然后能够一遍树形DP找到最小值或者二分+推断是否訪问到叶子节点. #include <iostream ...
随机推荐
- 阿里云弹性容器实例产品 ECI ——云原生时代的基础设施
阿里云弹性容器实例产品 ECI ——云原生时代的基础设施 1. 什么是 ECI 弹性容器实例 ECI (Elastic Container Instance) 是阿里云在云原生时代为用户提供的基础计算 ...
- Mybatis源码解析 - mapper代理对象的生成,你有想过吗
前言 开心一刻 本人幼教老师,冬天戴帽子进教室,被小朋友看到,这时候,有个小家伙对我说:老师你的帽子太丑,赶紧摘了吧.我逗他:那你好好学习,以后给老师买个漂亮的?这孩子想都没想立刻回答:等我赚钱了,带 ...
- 痞子衡嵌入式:ARM Cortex-M内核那些事(5)- 指令集
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是ARM Cortex-M指令集. 指令集 指令长度(bits) 包含指令 CortexM0 CortexM0+ CortexM1 Cor ...
- 详解什么是平衡二叉树(AVL)(修订补充版)
详解什么是平衡二叉树(AVL)(修订补充版) 前言 Wiki:在计算机科学中,AVL树是最早被发明的自平衡二叉查找树.在AVL树中,任一节点对应的两棵子树的最大高度差为1,因此它也被称为高度平衡树.查 ...
- ROS 101
https://www.clearpathrobotics.com/blog/2014/01/how-to-guide-ros-101/ 什么是ROS ROS(robot operating syst ...
- 第7章 贡献 - Identity Server 4 中文文档(v1.0.0)
我们对社区贡献非常开放,但您应该遵循一些指导原则,以便我们可以毫不费力地处理这个问题. 7.1 如何贡献? 最简单的方法是打开一个问题并开始讨论.然后我们可以决定是否以及如何实现功能或更改.如果您应提 ...
- __tostring()和__invoke()的用法
PHP有很多内置的魔术方法,这里我们聊哈tostring和involk吧. __tostring()魔术方法 将一个对象当做一个字符串来使用时,会自动调用该方法,并且在该方法中,可以返回一定的字符串, ...
- Spring笔记03_AOP
目录 1. AOP 1.1 AOP介绍 1.1.1 什么是AOP 1.1.2 AOP实现原理 1.1.3 AOP术语[掌握] 1.2 AOP的底层实现(了解) 1.2.1 JDK动态代理 1.2.2 ...
- Bable实现由ES6转译为ES5
Babel是一个广泛使用的转码器,可以将ES6代码转译为ES5代码,从而在现有环境下执行. 举例说明: 转译前(ES6格式)代码如下: let User = { name : '张三', age : ...
- 广州.NET微软技术俱乐部 微信群有用信息集锦
考虑到广州.NET微软技术俱乐部 微信群 十分活跃. 有用信息很有可能被淹没. 所以建立此贴. 首先群的活跃是十分重要的. 所以我是不可能把群搞得像技术论坛和github一样, 因为微信群的定位我在& ...