codesforces 671D Roads in Yusland
Mayor of Yusland just won the lottery and decided to spent money on something good for town. For example, repair all the roads in the town.
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.
设f[i]为控制了i点的子树的费用
显然f是存在后效性的,因为当前选的工人会影响祖先的状态
最暴力的方法f[x][i]表示工人最高控制到x,控制了i的子树,不过显然超时
想办法消除后效性
我们考虑把一些工人的属性叠加到一个工人上,那么我们最后查询时只要查询某些能维修完整棵树的最小值
因为我们已经的到了这几棵子树的最优答案,并且子树之间互不影响,那么我们考虑把控制其他子树费用叠加到一个子树工人上
假设儿子有p1,p2,p3,tot=∑f[p]
p1的儿子的工人加上tot-f[p1],其他同理
也就是说,每一个工人都有控制其他所有子树的花费
也就是说,祖先x要用到p儿子这个工人时,就可以直接算出控制p儿子及x的费用
而且没有后效性,因为工人存了包含此工人的最优解,而且工人一直到vi被消掉之前,
都可以覆盖当前点,所以把工人都计算,肯定能算出最优解
因为工人在到vi之前都需要
而且对于计算一个节点的f,我们要给开始的工人赋值,给结束的工人消值,且给子节点所有工人加数
所以我们用dfs序维护以工人为下标的线段树,这样给子节点的工人加数等于线段树的区间加法
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- typedef long long ll;
- struct Node
- {
- int next,to;
- }edge[],edgeS[],edgeT[];
- int num,numS,numT,head[],headS[],headT[];
- int L[],R[],cnt,dfn[],n,m;
- ll c[],lazy[],val[],inf=2e15,f[];
- void add(int u,int v)
- {
- num++;
- edge[num].next=head[u];
- head[u]=num;
- edge[num].to=v;
- }
- void addS(int u,int v)
- {
- numS++;
- edgeS[numS].next=headS[u];
- headS[u]=numS;
- edgeS[numS].to=v;
- }
- void addT(int u,int v)
- {
- numT++;而且没有后效性,因为
- edgeT[numT].next=headT[u];
- headT[u]=numT;
- edgeT[numT].to=v;
- }
- void pushup(int rt)
- {
- c[rt]=min(c[rt*],c[rt*+]);
- }
- void pushdown(int rt)
- {
- if (lazy[rt])
- {
- c[rt*]+=lazy[rt];
- c[rt*+]+=lazy[rt];
- lazy[rt*]+=lazy[rt];
- lazy[rt*+]+=lazy[rt];
- lazy[rt]=;
- }
- }
- void build(int rt,int l,int r)
- {
- c[rt]=inf;
- if (l==r)
- return;
- int mid=(l+r)/;
- build(rt*,l,mid);
- build(rt*+,mid+,r);
- }
- void prework(int x,int pa)
- {int i;
- L[x]=cnt+;
- for (i=headS[x];i;i=edgeS[i].next)
- {
- int v=edgeS[i].to;
- dfn[v]=++cnt;
- }
- for (i=head[x];i;i=edge[i].next)
- {
- int v=edge[i].to;
- if (v!=pa)
- prework(v,x);
- }
- R[x]=cnt;
- }
- void update(int rt,int l,int r,int x,ll d)
- {
- if (l==r)
- {
- c[rt]=min(inf,d);
- return;
- }
- pushdown(rt);
- int mid=(l+r)/;
- if (x<=mid) update(rt*,l,mid,x,d);
- else update(rt*+,mid+,r,x,d);
- pushup(rt);
- }
- void change(int rt,int l,int r,int L,int R,ll d)
- {
- if (L>R) return;
- if (l>=L&&r<=R)
- {
- c[rt]+=d;
- c[rt]=min(c[rt],inf);
- lazy[rt]+=d;
- lazy[rt]=min(lazy[rt],inf);
- return;
- }
- pushdown(rt);
- int mid=(l+r)/;
- if (L<=mid) change(rt*,l,mid,L,R,d);
- if (R>mid) change(rt*+,mid+,r,L,R,d);
- pushup(rt);
- }
- ll query(int rt,int l,int r,int L,int R)
- {
- if (L>R) return inf;
- if (l>=L&&r<=R)
- {
- return c[rt];
- }
- pushdown(rt);
- int mid=(l+r)/;
- ll s=inf;
- if (L<=mid) s=min(s,query(rt*,l,mid,L,R));
- if (R>mid) s=min(s,query(rt*+,mid+,r,L,R));
- pushup(rt);
- return s;
- }
- void dfs(int x,int pa)
- {int i;
- ll tot=;
- for (i=head[x];i;i=edge[i].next)
- {
- int v=edge[i].to;
- if (v==pa) continue;
- dfs(v,x);
- tot+=f[v];
- tot=min(tot,inf);
- }
- if (x==)
- {
- f[]=tot;
- return;
- }
- for (i=headS[x];i;i=edgeS[i].next)
- {
- int v=edgeS[i].to;
- update(,,m,dfn[v],tot+val[v]);
- }
- for (i=headT[x];i;i=edgeT[i].next)
- {
- int v=edgeT[i].to;
- update(,,m,dfn[v],inf);
- }
- for (i=head[x];i;i=edge[i].next)
- {
- int v=edge[i].to;
- if (v==pa) continue;
- change(,,m,L[v],R[v],tot-f[v]);
- }
- f[x]=query(,,m,L[x],R[x]);
- }
- int main()
- {int i,u,v;
- cin>>n>>m;
- for (i=;i<=n-;i++)
- {
- scanf("%d%d",&u,&v);
- add(u,v);add(v,u);
- }
- for (i=;i<=m;i++)
- {
- scanf("%d%d%I64d",&u,&v,&val[i]);
- addS(u,i);addT(v,i);
- }
- prework(,);
- build(,,m);
- dfs(,);
- if (f[]!=inf) cout<<f[];
- else cout<<-;
- }
codesforces 671D Roads in Yusland的更多相关文章
- Codeforces 671D Roads in Yusland [树形DP,线段树合并]
洛谷 Codeforces 这是一个非正解,被正解暴踩,但它还是过了. 思路 首先很容易想到DP. 设\(dp_{x,i}\)表示\(x\)子树全部被覆盖,而且向上恰好延伸到\(dep=i\)的位置, ...
- codeforces 671D Roads in Yusland & hdu 5293 Tree chain problem
dp dp优化 dfs序 线段树 算是一个套路.可以处理在树上取链的问题.
- Codeforces 671D. Roads in Yusland(树形DP+线段树)
调了半天居然还能是线段树写错了,药丸 这题大概是类似一个树形DP的东西.设$dp[i]$为修完i这棵子树的最小代价,假设当前点为$x$,但是转移的时候我们不知道子节点到底有没有一条越过$x$的路.如果 ...
- CF 671D Roads in Yusland
弄完之后点进去一看,竟然是div1的D题……最近真是天天被题虐哭 推荐这一篇博客 https://www.cnblogs.com/Sakits/p/8085598.html 感觉讲清楚了,也是基本照着 ...
- Codeforces 671 D. Roads in Yusland
题目描述 Mayor of Yusland just won the lottery and decided to spent money on something good for town. Fo ...
- 【CF671D】Roads in Yusland(贪心,左偏树)
[CF671D]Roads in Yusland(贪心,左偏树) 题面 洛谷 CF 题解 无解的情况随便怎么搞搞提前处理掉. 通过严密(大雾)地推导后,发现问题可以转化成这个问题: 给定一棵树,每条边 ...
- [Codeforces671D]Roads in Yusland
[Codeforces671D]Roads in Yusland Tags:题解 题意 luogu 给定以1为根的一棵树,有\(m\)条直上直下的有代价的链,求选一些链把所有边覆盖的最小代价.若无解输 ...
- 【CF617D】Roads in Yusland
[CF617D]Roads in Yusland 题面 蒯的洛谷的 题解 我们现在已经转化好了题目了,戳这里 那么我们考虑怎么求这个东西,我们先判断一下是否所有的边都能被覆盖,不行的话输出\(-1\) ...
- 【CodeForces】671 D. Roads in Yusland
[题目]D. Roads in Yusland [题意]给定n个点的树,m条从下往上的链,每条链代价ci,求最少代价使得链覆盖所有边.n,m<=3*10^5,ci<=10^9,time=4 ...
随机推荐
- 20162330 实验三 《敏捷开发与XP实践》 实验报告
2016-2017-2 实验报告目录: 1 2 3 4 5 20162330 实验三 <敏捷开发与XP实践> 实验报告 课程名称:<程序设计与数据结构> 学生班级:1623班 ...
- hdu 3642 Get The Treasury
Get The Treasury http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Othe ...
- asp.net web api 控制器
1控制器操作的参数 控制器操作的参数可以是内置类型也可以是自定义类型,无参也是允许的. 2控制器操作返回值 类型 说明 void 操作返回值为void时,Web API返回空HTTP响应,其状态码为2 ...
- Node入门教程(1)目录
aicoder.com 全栈实习之简明 Node 入门文档 aicoder.com 线下实习: 不 8000 就业,不还实习费. 如果需要转载本文档,请联系老马,Q: 515154084 JS基础教程 ...
- 织梦dedecms默认网站地图sitemap.html优化
网站地图对于网站优化很重要,搜索引擎就是靠网站地图去收录网站页面,本文主要讲解优化织梦自带的网站地图功能. 织梦自带的网站地图使用方法:织梦后台--生成--HTML更新--更新网站地图,可以在 ...
- 06_Python的数据类型3元组,集合和字典_Python编程之路
上一节跟大家讲了Python的列表,当然不是完整的讲完,后续我们还会提到,这一节我们还是来讲Python的数据类型 首先要讲到的就是元组 元组其实拥有列表的一些特性,可以存储不同类型的值,但在某些方面 ...
- 关于TomCat上传文件中文名乱码的问题
最近在学习TomCat文件上传这一部分,由于文件上传必须要三个条件: 1.表单提交方式必须为Post 2.表单中需要有<input type="file">元素,还需要 ...
- js常用API方法
String对象常用的API:API指应用程序编程接口,实际上就是一些提前预设好的方法. charAt() 方法可返回指定位置的字符. stringObject.charAt(index) index ...
- WPF 自定义ComboBox样式
一.ComboBox基本样式 ComboBox有两种状态,可编辑和不可编辑状态.通过设置IsEditable属性可以切换控件状态. 先看基本样式效果: 基本样式代码如下: <!--ComboBo ...
- 前端之CSS内容
一.CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素. 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化(渲染). 二.CSS语法 1 ...