Problem

Codeforces-671D

题意概要:给定一棵 \(n\) 点有根树与 \(m\) 条链,链有费用,保证链端点之间为祖先关系,问至少花费多少费用才能覆盖整棵树(\(n-1\) 条边)

\(n,m\leq 3\times 10^5\)

Solution

有一个线性规划的对偶式子(是从这篇里学习的):

\(\max\{c^Tx|Ax\leq b\}=\min\{b^Ty|A^Ty\geq c\}\)

(其中 \(x,y,b,c\) 为列向量,\(A\) 为一个矩阵)

其理解可以参照下面这个模型:

第一个式子中:工厂主有 \(n\) 个产品,其中 \(A\) 为这些产品所需原材料的数量,\(x\) 为产品生产数量,\(c\) 为生产一件产品的收益,\(b\) 为原材料数量

第二个式子中:喻同学有 \(m\) 种原材料,其中 \(A^T\) 上述矩阵的转置,\(b,c\) 同理,\(y\) 表示给原材料的定价

第一个式子中的现实意义:工厂主在使用现有原材料的情况下,生产产品所得最大收益

第二个式子中的现实意义:喻同学给工厂主的原材料定价,使得工厂主无论如何都无法获得任何收益,在此情况下尽量使得工厂主支出最少

由于工厂主要最大化自己的收益,而在喻同学的操作下,工厂主已经无法获益,要最大化自己收益(可能为负)只能尽量减少支出

由现实意义可以得出该式子,但严谨证明暂略


回到这题,由于求最小的花费不容易求,使用上述对偶关系进行转换:

原题套用第二个式子:

\(b^T\) : 每条链的费用

\(y\) : 每条链是否选择

\(A^T\) : 每条边是否被每条链覆盖

\(c\) : 每条边至少覆盖一次

求费用最小

对偶成第一个式子:

\(c^T\) : 每条边被覆盖一次

\(x\) : 给每条边构造的权值

\(A\) : 每条链是否覆盖每个点

\(b\) : 每条链的费用

求构造值之和最大

所以原题转化成:给定一棵树,要求给每条边构造一个权值,使得对于每条链而言,链上边权值之和不大于当前链的权值。由于原题保证链一定有祖先关系,可以左偏树贪心

Code

/*
Problem Source : cf-671D
Author : oier_hzy
Time : Nov 19 2019
*/
#include <bits/stdc++.h>
using namespace std; inline void read(int&x){
char c11=getchar();x=0;while(!isdigit(c11))c11=getchar();
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();
} const int N = 301000;
struct Edge{int v,w,nxt;} a[N*3];
int head[N], Head[N];
int tag[N], cov[N];
int dep[N], len[N];
int rt[N], ls[N], rs[N];
int n,m,_,tot; long long Ans; inline void add(int x,int y,int z,int*arr){a[++_].v = y, a[_].w = z, a[_].nxt = arr[x], arr[x] = _;} struct node{int w, ps;}t[N]; inline void put_tag(int x,int y) {t[x].w += y, tag[x] += y;}
inline void down_tag(int x){
int&v = tag[x];
if(!v) return ;
if(ls[x]) put_tag(ls[x], v);
if(rs[x]) put_tag(rs[x], v);
v = 0;
} int merge(int x,int y){
if(!x or !y) return x | y;
down_tag(x), down_tag(y);
if(t[x].w > t[y].w) swap(x,y);
rs[x] = merge(rs[x], y);
if(len[ls[x]] < len[rs[x]]) swap(ls[x], rs[x]);
len[x] = len[rs[x]] + 1;
return x;
} void dfs(int x,int las){
for(int i=head[x];i;i=a[i].nxt)
if(a[i].v != las){
dep[a[i].v] = dep[x] + 1;
dfs(a[i].v,x);
rt[x] = merge(rt[x], rt[a[i].v]);
cov[x] += cov[a[i].v];
}
if(x != 1 and !cov[x]) puts("-1"), exit(0);
for(int i=Head[x];i;i=a[i].nxt){
t[++tot] = (node) {a[i].w, a[i].v};
rt[x] = merge(rt[x], tot);
}
while(rt[x] and dep[t[rt[x]].ps] >= dep[x]) {
down_tag(rt[x]);
rt[x] = merge(ls[rt[x]], rs[rt[x]]);
}
Ans += t[rt[x]].w, put_tag(rt[x], -t[rt[x]].w);
} int main(){
read(n), read(m);
int x,y,z;
for(int i=1;i<n;++i){
read(x), read(y);
add(x,y,0,head);
add(y,x,0,head);
}
while(m--){
read(x), read(y), read(z);
++cov[x], --cov[y];
add(x,y,z,Head);
}
dfs(1,0);
printf("%lld\n",Ans);
return 0;
}

题解-Codeforces671D Roads in Yusland的更多相关文章

  1. [Codeforces671D]Roads in Yusland

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

  2. Codeforces 671 D. Roads in Yusland

    题目描述 Mayor of Yusland just won the lottery and decided to spent money on something good for town. Fo ...

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

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

  4. 【CF617D】Roads in Yusland

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

  5. 【CodeForces】671 D. Roads in Yusland

    [题目]D. Roads in Yusland [题意]给定n个点的树,m条从下往上的链,每条链代价ci,求最少代价使得链覆盖所有边.n,m<=3*10^5,ci<=10^9,time=4 ...

  6. codesforces 671D Roads in Yusland

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

  7. 题解-CodeForces835F Roads in the Kingdom

    Problem CodeForces-835F 题意:求基环树删去环上任意一边后直径最小值,直径定义为所有点对最近距离的最大值 Solution 首先明确删去环上一点是不会影响树内直径的,所以应当先把 ...

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

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

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

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

随机推荐

  1. centos7之zabbix3.2代理(zabbix-proxy)搭建

    zabbix的强大之处也在于它是分布式监控系统,对于多机房大集群情况下,肯定不是一台zabbix-server服务器来进行信息的收集等工作,就要用到代理了.在记录zabbix-proxy之前,要系统的 ...

  2. list遍历时删除的坑

    1.测试代码如下: public class StrTest { public static void main(String[] args) { ArrayList<String> li ...

  3. 2019-04-16 SpringMVC 学习笔记

    1. 配置过程: ① 配置servlet(org.springframework.web.servlet.DiapatcherServlet)拦截请求 ② SpringMVC的默认配置文件:servl ...

  4. cesium-navigation 使用(非require,es6引用)

    cesium-navigation-es6(非require,es6引用) 为什么你建立cesium-navigation插件? 插件形式不影响之前项目使用,es6 使用 首先,所有的Cesiumjs ...

  5. 2018年第九届蓝桥杯题目(C/C++B组)汇总

    第一题 标题:第几天 2000年的1月1日,是那一年的第1天. 那么,2000年的5月4日,是那一年的第几天? 注意:需要提交的是一个整数,不要填写任何多余内容. 解题思路: 1.  判断2月有几天, ...

  6. python多线程中join()方法和setDaemon()方法的区别

    """ join()方法:主线程A中,创建了子线程B,并且在主线程中调用了B.join()方法,那么主线程A会在调用的地方等待,直到子线程B完成操作后,才可以接着往下执行 ...

  7. 远离go path,弃用go get,使用go mod 进行go语言的学习

    标题说的是go语言的学习,因为我也没做过开发 文章要解决的仅仅是一个问题 当你使用go get 无论如何get不到所需的包的问题 第一步就是下载goland 新手极其推荐goland,因为直接使用gl ...

  8. placeholder中文字添加换行方法

    需求: 文本域内的提示文字两行显示 解决方案: 表示回车 表示换行 <textarea id="textarea" maxlength="22" plac ...

  9. ML笔记-sklearn.classification_report

    主要用于显示主要分类指标的文本报告,在报告中显示每个类的精确度.召回率.F1等信息 首先数据测试结果分为以下4种情况: TP:预测为正,实现为正 FP:预测为正,实现为负 FN:预测为负,实现为正 T ...

  10. Oracle下查看索引的语句

    1. 查询一张表里面索引  select * from user_indexes where table_name=upper('bills'); 2. 查询被索引字段  select * from ...