题目描述

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.

题目大意:

每一条边都需要被修建一次,雇佣第\(i\)个工人需要花 \(ci\) 的钱,能够帮你修建 \(ui\),\(vi\),之间的所有道路,并且保证 \(vi\) 是,\(ui\) 到根的路径上的点

解题报告:

用时:2h,6MLE

分析这题,叶子节点必须选,然后对于没有被覆盖的也必须从子树中选,但是需要决策,所以只能DP,考虑状态:

很容易想到最暴力的DP,定义 \(f[x][j]\),表示 \(x\) 子树内的边都被修过,且已选工人最远能覆盖到的深度为 \(j\),转移非常简单,但是复杂度不对,考虑消除第二维:不会.....

容易想到树链剖分,即把当前节点能更新到的父节点做一遍链剖,更新线段树

显然不行,因为不能保证其他子树都被覆盖

参考题解:

思想非常巧妙,大概是把其他子树中的DP值累加到某一棵子树上,这样就巧妙的使得线段树中的DP值都是合法的了,为了消除在 \(vi\) 结束的影响,我们在 \(ui\) 和 \(vi\) 上分别挂链,然后dfs时对应线段树中添加删除即可

注意实现时可以考虑不参考我的方法,其实不一定只对关键点建立线段树,不然细节很多

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=300005;const ll inf=2e15;
int head[N],nxt[N<<2],to[N<<2],num=0,n,m,val[N],dfn[N],DFN=0,L[N],R[N],s[N],t[N];
void link(int x,int y,int *h){nxt[++num]=h[x];to[num]=y;h[x]=num;}
void priwork(int x,int last){
L[x]=DFN+1;
for(int i=s[x];i;i=nxt[i])dfn[to[i]]=++DFN;
for(int i=head[x];i;i=nxt[i])
if(to[i]!=last)priwork(to[i],x);
R[x]=DFN;
}
ll tree[N<<2],mark[N<<2],f[N];
#define ls (node<<1)
#define rs (node<<1|1)
void build(int l,int r,int node){
tree[node]=inf;if(l==r)return ;
int mid=(l+r)>>1;
build(l,mid,ls);build(mid+1,r,rs);
tree[node]=Min(tree[ls],tree[rs]);
}
il void updata(int l,int r,int node,int sa,int se,ll to){
if(sa>se)return ;
if(l>se || r<sa)return ;
if(sa<=l && r<=se){
tree[node]=Min(tree[node]+to,inf);
mark[node]=Min(mark[node]+to,inf);
return ;
}
int mid=(l+r)>>1;
updata(l,mid,ls,sa,se,to);updata(mid+1,r,rs,sa,se,to);
tree[node]=Min(tree[ls],tree[rs])+mark[node];
}
il void Modify(int l,int r,int node,int sa,ll to){
if(l==r){tree[node]=Min(to,inf);return ;}
int mid=(l+r)>>1;
if(sa<=mid)Modify(l,mid,ls,sa,to);
else Modify(mid+1,r,rs,sa,to);
tree[node]=Min(tree[ls],tree[rs])+mark[node];
}
il ll query(int l,int r,int node,int sa,int se){
if(sa>se)return inf;
if(l==sa && r==se)return tree[node];
int mid=(l+r)>>1;
if(sa>mid)return query(mid+1,r,rs,sa,se)+mark[node];
else if(se<=mid)return query(l,mid,ls,sa,se)+mark[node];
return min(query(l,mid,ls,sa,mid),query(mid+1,r,rs,mid+1,se))
+mark[node];
}
il void dfs(int x,int last){
int u;ll tot=0;
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(to[i]==last)continue;
dfs(u,x);
tot+=f[u];tot=Min(tot,inf);
}
if(x==1){f[x]=tot;return ;}
for(int i=s[x];i;i=nxt[i])Modify(1,m,1,dfn[to[i]],tot+val[to[i]]);
for(int i=t[x];i;i=nxt[i])Modify(1,m,1,dfn[to[i]],inf);
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(u==last)continue;
updata(1,m,1,L[u],R[u],tot-f[u]);
}
f[x]=query(1,m,1,L[x],R[x]);
}
void work()
{
int x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
link(x,y,head);link(y,x,head);
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&val[i]);
link(x,i,s);link(y,i,t);
}
priwork(1,1);build(1,m,1);dfs(1,1);
if(f[1]!=inf)printf("%lld\n",f[1]);
else puts("-1");
} int main(){work();return 0;}

Codeforces 671 D. 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 ...

  2. codesforces 671D Roads in Yusland

    Mayor of Yusland just won the lottery and decided to spent money on something good for town. For exa ...

  3. 【CF671D】Roads in Yusland(贪心,左偏树)

    [CF671D]Roads in Yusland(贪心,左偏树) 题面 洛谷 CF 题解 无解的情况随便怎么搞搞提前处理掉. 通过严密(大雾)地推导后,发现问题可以转化成这个问题: 给定一棵树,每条边 ...

  4. [Codeforces671D]Roads in Yusland

    [Codeforces671D]Roads in Yusland Tags:题解 题意 luogu 给定以1为根的一棵树,有\(m\)条直上直下的有代价的链,求选一些链把所有边覆盖的最小代价.若无解输 ...

  5. 【CF617D】Roads in Yusland

    [CF617D]Roads in Yusland 题面 蒯的洛谷的 题解 我们现在已经转化好了题目了,戳这里 那么我们考虑怎么求这个东西,我们先判断一下是否所有的边都能被覆盖,不行的话输出\(-1\) ...

  6. Codeforces 835 F. Roads in the Kingdom

    \(>Codeforces\space835 F. Roads in the Kingdom<\) 题目大意 : 给你一棵 \(n\) 个点构成的树基环树,你需要删掉一条环边,使其变成一颗 ...

  7. Codeforces 671D Roads in Yusland [树形DP,线段树合并]

    洛谷 Codeforces 这是一个非正解,被正解暴踩,但它还是过了. 思路 首先很容易想到DP. 设\(dp_{x,i}\)表示\(x\)子树全部被覆盖,而且向上恰好延伸到\(dep=i\)的位置, ...

  8. codeforces 671D Roads in Yusland & hdu 5293 Tree chain problem

    dp dp优化 dfs序 线段树 算是一个套路.可以处理在树上取链的问题.

  9. Codeforces 671D. Roads in Yusland(树形DP+线段树)

    调了半天居然还能是线段树写错了,药丸 这题大概是类似一个树形DP的东西.设$dp[i]$为修完i这棵子树的最小代价,假设当前点为$x$,但是转移的时候我们不知道子节点到底有没有一条越过$x$的路.如果 ...

随机推荐

  1. 小草手把手教你 LabVIEW 串口仪器控制——初识VISA串口

    有些人,学习一样东西时候,喜欢现成的例子.很多人学习一门技术,都喜欢现成的例子开始,比如学单片机的啊,最开始都是修改的例子吧,学语言的也是.最开始都是模仿.这个年头看书上的理论知识太浪费时间了.所以啊 ...

  2. asp.net web api 控制器

    1控制器操作的参数 控制器操作的参数可以是内置类型也可以是自定义类型,无参也是允许的. 2控制器操作返回值 类型 说明 void 操作返回值为void时,Web API返回空HTTP响应,其状态码为2 ...

  3. JAVA_SE基础——10.变量的作用域

    <pre name="code" class="java"> 上个月实在太忙了,从现在开始又可以静下心来写blog了. 变量的作用域指 可以使用此变 ...

  4. AngularJS1.X学习笔记8-自定义指令(上)

    AngulaJS的指令是一种非常强大的特性,一个ng-repeat就能让我们非常方便的展示一个数据列表,指令相当于是一个组件,为我们将一些东西封装起来了,提供了复用的可能性.个人认为自定义指令还是比较 ...

  5. 分贝块---dBblock

    分贝,用英语来表达的话,是decibel,是量度两个相同单位之数量比例的计量单位,主要用于度量声音强度,常用dB表示. 块,block,在百度百科中,指数据库中的最小存储和处理单位,包含块本身的头信息 ...

  6. 09_Python定义方法_Python编程之路

    有关Python判断与循环的内容我们上几节已经跟大家一起学习了,这一节我们主要针对def 做一个讲解 def 定义一个方法 在项目编程中,我们往往要做很多重复的事,比如一个排序的功能(当然Python ...

  7. Angular 学习笔记 ( CDK - Layout )

    简单说就是 js 的 media query. 1. BreakpointObserver  const layoutChanges = this.breakpointObserver.observe ...

  8. Mysql官方文档翻译系列14.18--MySql备份与恢复

    原文链接: (https://dev.mysql.com/doc/refman/5.7/en/innodb-backup-recovery.html) The key to safe database ...

  9. JAVA通过注解处理器重构代码,遵循单一职责

    前言:最近在看一个内部网关代码的时候,发现处理Redis返回数据这块写的不错,今天有时间好好研究下里面的知识点. 业务流程介绍: #项目是采用Spring Boot框架搭建的.定义了一个@Redis注 ...

  10. jacascript 事件对象event

    前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 在触发DOM上的某个事件时,会产生一个事件对象 event,这个对象中包含着所有与事件有关的信息.所有浏览 ...