题目链接

题目要求我们求出选出若干条路径并最小化花费,如果这是在链上,我们可以考虑直接枚举每条路径的右端点 dp,那树呢?把路径剖分整个覆盖的集合就不一定连续了,没法 dp,况且题目里给了很强的条件:路径一定是从孩子到祖先,硬转链用不上这个性质,貌似不太对。

上述思考启发我们利用树的形态设计算法,而利用节点的子树分割成子问题是一个通常的思考方向,我们从此处入手,考虑如果要覆盖一棵树需要什么条件,首先,根节点的每棵子树必须被覆盖,并且还要有一条能向外延伸的边以覆盖连接根节点和子树根节点的边。

考虑设计 dp 以维护上述条件,为了维护前者,我们可以钦定每个节点的状态所选择的解中子树全部被覆盖;而后者,由于子树内所有节点的祖先并都在固定的一条链上,我们可以添加一维确定向外延伸的长度。具体地,我们设 \(f_{u,j}\) 表示完全覆盖节点 \(u\) 的子树且向外延伸了 \(j\) 个长度的最小花费。

转移是显然的,设 \(g_u=\min f_{u,j}\),则 \(f_{u,j}=\min \{f_{v,j}\}+\sum_{k\in son(v)} g_k -g_v\)。这个做法是 \(O(n^2)\) 的。

由于转移比较简单,我们考虑能不能用数据结构维护第二维,需要支持合并取 min 和全局加,用线段树合并就可以维护,时间和空间复杂度都是 \(O((n+m)\log n)\) 的。

但是本题空间复杂度限制比较紧,注意到线段树中有很多没有用的节点,并且不能动态调整空间。考虑换成平衡树,每个节点储存二元组 \((j,cost)\) 表示向上延伸 \(j\) 距离花费 \(cost\),全局加可以直接打标记,合并可以直接启发式合并,全部插到里面就行,注意为了保证复杂度,如果有向上延伸相同距离的状态我们只能保留一个。

问题是取 min,由于刚才我们已经要求平衡树按第一维排序,我们不好直接求全局 min,但是注意到如果一个状态相比于另一个能覆盖更前面的边但是花费也更小,我们不必保留另一个状态,因此在满足一维排好序的情况下另一位也排好了。平衡树可以用 set,时间复杂度 \(O((n+m)\log^2 n)\),但是空间复杂度变成了线性,可以通过。

// Problem: Roads in Yusland
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF671D
// Memory Limit: 250 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org) #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<set>
#define ll long long
#define N 300005
using namespace std;
ll read(){
ll x=0;char ch=getchar();
while(ch<'0' || ch>'9') ch=getchar();
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x;
}
ll e,head[N<<1],nex[N<<1],to[N<<1],dep[N],tag[N],rt[N];
struct Node{
ll num,val;
bool operator <(const Node &x)const{
return num>x.num;
}
};
vector<Node> E[N];
set<Node> t[N];
void add(ll u,ll v){
to[++e]=v;nex[e]=head[u];head[u]=e;
to[++e]=u;nex[e]=head[v];head[v]=e;
}
ll flag;
void insert(ll u,ll num,ll val){
if(t[u].size()==0){t[u].insert((Node){num,val});return;}
auto it=t[u].lower_bound((Node){num,val});
if(it==t[u].end() || (it->num)!=num){
if(it!=t[u].end() && it->val<=val)return;
if(it==t[u].begin()){t[u].insert((Node){num,val});return;}
auto itr=it,itl=it;
while(itl!=t[u].begin()){
itl--;if(itl->val<val){itl++;break;}
}
if(itl!=itr)t[u].erase(itl,itr);
t[u].insert((Node){num,val});return;
}
if(it->val<=val) return;
it++;auto itr=it;it--;
while(it!=t[u].begin()){
it--;if(it->val<val){it++;break;}
}
t[u].erase(it,itr);
t[u].insert((Node){num,val});
}
void dfs(ll u,ll fa){
rt[u]=u;
ll tot=0;dep[u]=dep[fa]+1;
for(ll i=head[u];i;i=nex[i]){
ll v=to[i];if(v==fa) continue;
dfs(v,u);if(flag) return;
if(t[rt[v]].size()==0){flag=1;return;}
if((t[rt[v]].begin()->num)>dep[u])t[rt[v]].erase(t[rt[v]].begin());
if(t[rt[v]].size()==0){flag=1;return;}
tot+=(t[rt[v]].begin()->val+tag[v]);tag[v]=-(t[rt[v]].begin()->val);
}
ll tmp=300001;
for(ll i=head[u];i;i=nex[i]){
ll v=to[i];if(v==fa) continue;
if(t[rt[v]].size()>t[rt[u]].size()){tmp=v;rt[u]=rt[v];tag[u]=tot+tag[v];}
}
for(ll i=head[u];i;i=nex[i]){
ll v=to[i];if(v==fa || rt[v]==rt[u]) continue;
for(auto it=t[rt[v]].begin();it!=t[rt[v]].end();it++){
insert(rt[u],it->num,it->val+tag[v]-tag[tmp]);
}
}
for(ll i=0;i<E[u].size();i++){
insert(rt[u],dep[E[u][i].num],E[u][i].val-tag[tmp]);
}
}
int main(){
ll n,m,u,v,w;n=read();m=read();
for(ll i=1;i<n;i++){u=read();v=read();add(u,v);}
for(ll i=1;i<=m;i++){
u=read();v=read();w=read();E[u].push_back((Node){v,w});
}
if(n==1){cout<<0;return 0;}
dfs(1,0);
if(flag) cout<<-1;
else cout<<(t[rt[1]].begin()->val)+tag[1];
return 0;
}

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

  1. CF671D Roads in Yusland

    一道很玄妙的题= = 我们考虑先考虑DP 那么有$f[x]=min(c+\sum f[y])$ $f[x]$表示覆盖x的子树和x->fa[x]的所有边最小代价 我们枚举一条边c覆盖的x-> ...

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

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

  3. Codeforces 671 D. Roads in Yusland

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

  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】671 D. Roads in Yusland

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

  7. codesforces 671D Roads in Yusland

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

  8. 题解-Codeforces671D Roads in Yusland

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

  9. CF671D:Roads in Yusland

    n<=300000个点的树,给m<=300000条带权路径(ui,vi,保证vi是ui的祖先)求覆盖整棵树每条边的最小权和. 好题好姿势!直观的看到可以树形DP,f[i]表示把点i包括它爸 ...

  10. 【CF671D】 Roads in Yusland(对偶问题,左偏树)

    传送门 洛谷翻译 CodeForces Solution emmm,先引入一个对偶问题的概念 \(max(c^Tx|Ax \leq b)=min(b^Ty|A^Ty \ge c)\) 考虑这个式子的现 ...

随机推荐

  1. 聊聊又拍云存储 S3 协议的使用

    近期,有细心的同学发现,在又拍云控制台中的云存储产品中增加了针对 S3 协议标准的兼容支持,授权用户通过 S3 协议标准对存储空间的数据进行读写操作.此配置操作之前是由人工协助的方式提供给用户使用的, ...

  2. Django CSRF cookie not set.

    错误原因 由于django框架的settings.py配置了中间件,为了防止跨站请求伪造,form表单POST方式会导致出现报错 解决办法: 将'django.middleware.csrf.Csrf ...

  3. oracle用户密码刷新

    1.查询用户信息 col username for a25 col account_status for a18 col profile for a20 select username,account ...

  4. nodejs中如何使用http创建一个服务

    http模块是nodejs中非常重要的一部分,用于开启一个服务,我们可以用它自定义接口供客户端使用.   开启服务的方式也比较简单,几行代码就可以搞定 const http = require('ht ...

  5. 图解Spark Graphx实现顶点关联邻接顶点的函数原理

    一.场景案例 在一张社区网络里,可能需要查询出各个顶点邻接关联的顶点集合,类似查询某个人关系比较近的都有哪些人的场景. 在用Spark graphx中,通过函数collectNeighbors便可以获 ...

  6. 商品详情接口设计:使用API调用获取淘宝商品数据的完整方案

    ​ 在如今的电商时代,获取商品的详细信息是实现商业化应用的基础.本文将详细介绍如何通过API调用来获取淘宝商品数据,并提供一个完整的商品详情接口设计方案,包括代码示例.开发人员可以根据此方案快速实现商 ...

  7. 基于ASP.NET ZERO,开发SaaS版供应链管理系统

    前言 在园子吸收营养10多年,一直没有贡献,目前园子危机时刻,除了捐款+会员,也鼓起勇气,发篇文助力一下. 2018年下半年,公司决定开发一款SaaS版行业供应链管理系统,经过选型,确定采用ABP(A ...

  8. oracle导入导出某个schema数据

    背景 公司之前部门拆分,但一些服务并没有拆分清楚.其中一个老服务,两个部门都在用,现在为了避免互相影响,决定克隆该服务.克隆就要克隆全套,当然也包括数据库,我们这个老服务,用的oracle,所以,就涉 ...

  9. 《Python魔法大冒险》 001 序章:少年小鱼的不平凡一天

    在一个普通的城市里,生活着一个名叫小鱼的少年.他是一名初中生,但在班级里,他的学习成绩总是垫底.同学们经常取笑他,有时甚至戏称他为"倒数王". 放学后,小鱼一个人走在回家的路上,他 ...

  10. Oracle为表添加约束

    转载自:https://blog.csdn.net/qq_38662525/article/details/94192475 创建一个学生表和院系表:院系表为主表,学生表为从表   create ta ...