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. ecshop 商品属性显示方法

    功能:在商品列表上,点击放大镜,显示商品所有属性以及其价格,效果如下: 方法/步骤: 1.编辑\admin\templates\goods_list.htm 模板,在 <!-- 商品搜索 --& ...

  2. redis常见问题

    1.redis满了,怎么处理? (1)内存淘汰策略(2)集群,动态增加redis服务器(推荐) 2.val比较大时(比如50MB),会有什么影响? 因为redis是单线程,多路IO复用的,所以当一个v ...

  3. 入坑MATLAB必会的吐血总结

    本渣想回过头来整理一下MATLAB的一些基本的知识(很多东西比较琐碎,应该系统的梳理梳理),下文中没有提到的,自己用help查即可. 此文用来存个档,便于回顾. 由于matlab各版本部分语法存在差异 ...

  4. 【CF1063D】Candies for Children 数学

    题目大意 有 \(n\) 个人排成一个圈,你有 \(k\) 颗糖,你要从第 \(l\) 个人开始发糖,直到第 \(r\) 个人拿走最后一颗糖.注意这 \(n\) 个人拍成了一个圈,所以第 \(n\) ...

  5. 【BZOJ4000】[TJOI2015]棋盘(矩阵快速幂,动态规划)

    [BZOJ4000][TJOI2015]棋盘(矩阵快速幂,动态规划) 题面 BZOJ 洛谷 题解 发现所有的东西都是从\(0\)开始编号的,所以状压只需要压一行就行了. 然后就可以随意矩乘了. #in ...

  6. bzoj3168 钙铁锌硒维生素 (矩阵求逆+二分图最小字典序匹配)

    设第一套为A,第二套为B 先对于每个B[i]判断他能否替代A[j],即B[i]与其他的A线性无关 设$B[i]=\sum\limits_{k}{c[k]*A[k]}$,那么只要看c[j]是否等于零即可 ...

  7. 没想到: System.out.println(n1 == f1 ? n1 : f1);

    int n1 = 404; float f1 = 404.0f; if(n1 == f1) { System.out.println("两者相等"); } System.out.p ...

  8. halcon+WinForm打开摄像头

    注意引用halcon.dll,项目属性平台一致(X64) using HalconDotNet;//引用halcon using System.Threading;//引用线程 namespace M ...

  9. Hexo next主题下添加天气插件

    最近在优化hexo 新搭建的博客,想给博客添加一个天气插件,奈何找了很久也没发现,好不容易发现一个天气插件 心知天气:https://www.seniverse.com/widget/get 运气不好 ...

  10. Windows10搭建FTP服务

    1.启用Windows10 Ftp服务 打开控制面板->程序和功能->启用或关闭windows功能然后如图: 2.配置FTP用户 我的电脑->右击点击管理->本地用户和组 在A ...