codefoeces problem 671D——贪心+启发式合并+平衡树
Yusland consists of n intersections connected by n - 1 bidirectional roads. One can travel from any intersection to any other intersection using only these roads.
There is only one road repairing company in town, named "RC company". Company's center is located at the intersection 1. RC company doesn't repair roads you tell them. Instead, they have workers at some intersections, who can repair only some specific paths. The i-th worker can be paid ci coins and then he repairs all roads on a path from ui to some vi that lies on the path from ui to intersection 1.
Mayor asks you to choose the cheapest way to hire some subset of workers in order to repair all the roads in Yusland. It's allowed that some roads will be repaired more than once.
If it's impossible to repair all roads print - 1.
The first line of the input contains two integers n and m (1 ≤ n, m ≤ 300 000) — the number of cities in Yusland and the number of workers respectively.
Then follow n−1 line, each of them contains two integers xi and yi (1 ≤ xi, yi ≤ n) — indices of intersections connected by the i-th road.
Last m lines provide the description of workers, each line containing three integers ui, vi and ci (1 ≤ ui, vi ≤ n, 1 ≤ ci ≤ 109). This means that the i-th worker can repair all roads on the path from vi to ui for ci coins. It's guaranteed that vi lies on the path from ui to 1. Note that vi and ui may coincide.
If it's impossible to repair all roads then print - 1. Otherwise print a single integer — minimum cost required to repair all roads using "RC company" workers.
6 5
1 2
1 3
3 4
4 5
4 6
2 1 2
3 1 4
4 1 3
5 3 1
6 3 2
8
In the first sample, we should choose workers with indices 1, 3, 4 and 5,
some roads will be repaired more than once but it is OK.
The cost will be equal to 2 + 3 + 1 + 2 = 8 coins.
————————————————————————————————————————
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#define LL long long
const int M=3e5+;
int read(){
int ans=,f=,c=getchar();
while(c<''||c>''){if(c=='-') f=-; c=getchar();}
while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
return ans*f;
}
LL ans;
int n,m;
int f[M];
int find(int x){while(f[x]!=x) x=f[x]=f[f[x]]; return x;}
int first[M],cnt;
struct node{int to,next;}e[*M];
void ins(int a,int b){e[++cnt]=(node){b,first[a]}; first[a]=cnt;}
void insert(int a,int b){ins(a,b); ins(b,a);}
int deep[M],fa[M];
int dfs(int x,int last){
for(int i=first[x];i;i=e[i].next){
int now=e[i].to;
if(now==last) continue;
deep[now]=deep[x]+;
fa[now]=x;
dfs(now,x);
}
}
struct pos{
int d,w;
bool operator <(const pos &x)const{return d!=x.d?d>x.d:w>x.w;}
};
std::multiset<pos>tr[M];
typedef std::multiset<pos>::iterator IT;
void delet(int x,pos p,int s){
p.w+=s;IT it=tr[x].upper_bound(p);
if(it!=tr[x].begin()){
it--;
while(it->w>=p.w){
if(it==tr[x].begin()){tr[x].erase(it);break;}
IT now=it; --now;
tr[x].erase(it);
it=now;
}
}
it=tr[x].upper_bound(p);
if(it==tr[x].end()||it->w>p.w) tr[x].insert(p);
}
int dec[M];
void push_ans(int x){
for(int i=first[x];i;i=e[i].next){
int now=e[i].to;
if(now==fa[x]) continue;
push_ans(now);
if(tr[now].size()>tr[x].size()) tr[x].swap(tr[now]),std::swap(dec[x],dec[now]);
for(IT it=tr[now].begin();it!=tr[now].end();it++) delet(x,*it,dec[x]-dec[now]);
tr[now].clear();
}
//if(x==2) for(IT it=tr[x].begin();it!=tr[x].end();it++) printf("A[%d %d]\n",it->d,it->w);
while(tr[x].size()){
IT it=tr[x].begin();
if(it->d==deep[x]) tr[x].erase(it);
else break;
}
if(x!=&&f[x]==x){
if(tr[x].empty()) puts("-1"),exit();
IT it=tr[x].begin();
ans+=it->w-dec[x];
dec[x]=it->w;
int v=x; while(deep[v]>it->d) v=f[v]=find(fa[v]);
tr[x].erase(it);
}
}
int main(){
int x,y,w;
n=read(); m=read();
for(int i=;i<=n;i++) f[i]=i;
for(int i=;i<n;i++) x=read(),y=read(),insert(x,y);
deep[]=; dfs(,-);
for(int i=;i<=m;i++){
x=read(); y=read(); w=read();
pos p=(pos){deep[y],w};
delet(x,p,);
}
push_ans();
printf("%lld\n",ans);
return ;
}
codefoeces problem 671D——贪心+启发式合并+平衡树的更多相关文章
- CEOI 2019 Day2 T2 魔法树 Magic Tree (LOJ#3166、CF1993B、and JOI2021 3.20 T3) (启发式合并平衡树,线段树合并)
前言 已经是第三次遇到原题. 第一次是在 J O I 2021 S p r i n g C a m p \rm JOI2021~Spring~Camp JOI2021 Spring Camp 里遇到的 ...
- Luogu5290 十二省联考2019春节十二响(贪心+启发式合并)
考虑链的做法,显然将两部分各自从大到小排序后逐位取max即可,最后将根计入.猜想树上做法相同,即按上述方式逐个合并子树,最后加入根.用multiset启发式合并即可维护.因为每次合并后较小集合会消失, ...
- BZOJ 2809: [Apio2012]dispatching( 平衡树 + 启发式合并 )
枚举树上的每个结点做管理者, 贪心地取其子树中薪水较低的, 算出这个结点为管理者的满意度, 更新答案. 用平衡树+启发式合并, 时间复杂度为O(N log²N) ------------------- ...
- bzoj 2809 左偏树\平衡树启发式合并
首先我们对于一颗树,要选取最多的节点使得代价和不超过m,那么我们可以对于每一个节点维护一个平衡树,平衡树维护代价以及代价的和,那么我们可以在logn的时间内求出这个子树最多选取的节点数,然后对于一个节 ...
- 【BZOJ1483】【HNOI2009】梦幻布丁(启发式合并,平衡树)
[BZOJ1483][HNOI2009]梦幻布丁 题面 题目描述 N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1 ...
- ☆ [HNOI2012] 永无乡 「平衡树启发式合并」
题目类型:平衡树启发式合并 传送门:>Here< 题意:节点可以连边(不能断边),询问任意两个节点的连通性与一个连通块中排名第\(k\)的节点 解题思路 如果不需要询问排名,那么并查集即可 ...
- 【pb_ds】【平衡树启发式合并】【并查集】bzoj2733 [HNOI2012]永无乡
用并查集维护联通性.对每个联通块维护一个平衡树.合并时启发式合并.比较懒,用了pb_ds. #include<cstdio> #include<ext/pb_ds/assoc_con ...
- 【BZOJ1483】[HNOI2009]梦幻布丁(平衡树启发式合并+并查集)
题目: BZOJ1483 分析: (这题码了一下午,码了近250行,但是意外跑的比本校各位神仙稍快,特写博客纪念) 首先能看出一个显然的结论:颜色段数只会变少不会变多. 我们考虑用并查集维护区间,对于 ...
- [多校 NOIP 联合模拟 20201130 T4] ZZH 的旅行(斜率优化dp,启发式合并,平衡树)
题面 题目背景 因为出题人天天被 ZZH(Zou ZHen) 吊打,所以这场比赛的题目中出现了 ZZH . 简要题面 数据范围 题解 (笔者写两个log的平衡树和启发式合并卡过的,不足为奇) 首先,很 ...
随机推荐
- vi/vim 命令使用详解
1.Linux下创建文件 vi test.txt 或者 vim test.txt 或者 touch test.txt 2.vi/vim 使用 基本上 vi/vim 共分为三种模式,分别是命令模式(Co ...
- Qt 在Label上面绘制罗盘
自己写的一个小小的电子罗盘的一个小程序,不过是项目的一部分,只可以贴绘制部分代码 效果如下图 首先开始自己写的时候,虽然知道Qt 的坐标系是从左上角开始的,所以,使用了算法,在绘制后,在移动回来,但是 ...
- 《机器学习实战》 in python3.x
机器学习实战这本书是在python2.x的环境下写的,而python3.x中好多函数和2.x中的名称或使用方法都不一样了,因此对原书中的内容需要校正,下面简单的记录一下学习过程中fix的部分 1.pr ...
- tinymce4.x 上传本地图片 (转载)
转载自:http://www.cnblogs.com/fhen/p/5809514.html tinymce4.x 上传本地图片 tinymce是一款挺不错的html文本编辑器.但是添加图片是直接 ...
- UVA 11882 Biggest Number(搜索+剪枝)
You have a maze with obstacles and non-zero digits in it: You can start from any square, walk in the ...
- winform timer时间间隔小于执行时间
如果SetTimer的时间间隔为t,其响应事件OnTimer代码执行一遍的时间为T,且T>t.这样,一次未执行完毕,下一次定时到,这时候程序会如何执行? 可能的情况:1.丢弃还未执行的代码,开始 ...
- sql between and 边界问题
1.不同的数据库对 BETWEEN...AND 操作符的处理方式是有差异的.需要自己测试 2.一般情况下.SQL Server中 between and是包括边界值的,not between不包括边界 ...
- android自定义View绘制圆形头像与椭圆头像
要实现这两种效果,需要自定义View,并且有两种实现方式. 第一种: public class BitmapShaders extends View { private BitmapSh ...
- Object类中的五种方法
clone() Object类源码:protected native Object clone() throws CloneNotSupportedException; 这里有个问题:为什么Sun公司 ...
- Xampp+Openfire+Spark的简单使用
Openfire与Spark的简单实用 1.安装Openfire 百度云 提取码:uu11 2.查找路径 /usr/local/openfire 这时候需要将openfire的文件属性都设置为 可读可 ...