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. VS编程,C#串口通讯,通过串口读取数据的一种方法

    一.可能需要的软件:1.虚拟串口vspd(Virtual Serial Port Driver,用来在电脑上虚拟出一对串口,模拟通讯. 2.友善串口调试助手,用来发送.读取数据. 二.思路1.查询本机 ...

  2. JavaScript的数据结构和算法

    所有JavaScript对象都有hasOwnProperty(value)的方法,用来返回一个表明对象是不是具有这个value Key值属性的布尔值. javaScript的方法 具有delete的方 ...

  3. 每个努力奋斗过的人,被不公正的际遇砸了满头包的时候,都有那么一瞬间的代入感。出生就是hard模式的人,早已经历了太多的劳其筋骨饿其体肤,再多的人为考验只会摧毁人对美好的向往。

    每个努力奋斗过的人,被不公正的际遇砸了满头包的时候,都有那么一瞬间的代入感.出生就是hard模式的人,早已经历了太多的劳其筋骨饿其体肤,再多的人为考验只会摧毁人对美好的向往.

  4. git在多迭代版本的应用

    名词解释: 1.迭代: 就是对于项目功能的一个分类.如项目需要新增一个地图功能,则地图功能是一个迭代. 2.gitlab机器人 操作: 1.如果将要进行一个新功能的开发,从稳定分支上拉取创建一个新的分 ...

  5. Vue-详解设置路由导航的两种方法

    https://www.cnblogs.com/superlizhao/p/8527317.html

  6. html中title小图标的实现

    <link rel="icon" href="picture.ico" type="image/x-icon"/> 注意:图片的 ...

  7. codeforces510D

    Fox And Jumping CodeForces - 510D Fox Ciel is playing a game. In this game there is an infinite long ...

  8. git学习03 - 撤销修改&删除文件

    撤销修改:git checkout -- filename :将工作区文件回到最近一次add 或者 commit的状态 撤销修改分为三种情况: 1.未提交至暂存区 使用git checkout -- ...

  9. gcc编译C源文件

    gcc编译C程序的主要过程是:预处理---编译---汇编---连接,其中:(以名为hello.c的源文件为例) 预处理:对各种预处理指令(#开头,如#include,#define)进行处理,以及删除 ...

  10. Error:java: 无效的目标发行版: 1.8

    出现问题: Error:java: 无效的目标发行版: 1.8 解决方法: file-setting--