AT4144-[ARC098D]Donation【Kruskal重构树,dp】
正题
题目链接:https://www.luogu.com.cn/problem/AT4144
题目大意
nnn个点mmm条边的一张无向联通图,每个点有两个值ai,bia_i,b_iai,bi。表示经过该点时需要拥有aia_iai元,该点需要捐献bib_ibi元。
任意起点,询问开始时至少多少钱才能捐献完所有点。
解题思路
WC2021WC2021WC2021和XJXJXJ杂题都讲过倒过来跑贪心的做法,不过我不知道怎么确定起点就爬了
首先定义ci=max{ai−bi,0}c_i=max\{a_i-b_i,0\}ci=max{ai−bi,0},因为ai≤bia_i\leq b_iai≤bi没有意义,所以这个cic_ici是有意义的部分。
图的话好像很麻烦,先搞一个KruskalKruskalKruskal重构树,不过这个是点权的,方法差不多,从小到大枚举点权就好了。
然后考虑一下我们的策略,肯定是走到一个点会顺便走完整个子树会更优。
所以设fxf_xfx表示走完子树xxx需要的权值,考虑如何转移,我们肯定是先从前面若干个子树走完捐献一遍后再捐献点xxx,然后走向最后一个子树。
以我们可以枚举最后一个子树yyy,然后转移方程就是
fx=min{sx−sy+max{fy,cx}}f_x=min\{s_x-s_y+max\{f_y,c_x\}\}fx=min{sx−sy+max{fy,cx}}
(这里sxs_xsx表示子树xxx的权值和)
这个转移的前面很好懂,就是捐赠其他子树,因为cxc_xcx一定大于它子树里的,所以不用考虑里面的ccc。之后后面那个就是两种限制取一个最大值。
时间复杂度O(nlogn)O(n\log n)O(nlogn)(排序复杂度)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define ll long long
using namespace std;
const ll N=1e5+10;
struct node{ll to,next;
}a[N];
ll n,m,tot,ls[N],fa[N],l[N],w[N],p[N],f[N];
vector<ll> G[N];bool v[N];
bool cmp(ll x,ll y)
{return l[x]<l[y];}
ll find(ll x)
{return (fa[x]==x)?x:(fa[x]=find(fa[x]));}
void addl(ll x,ll y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
void dp(ll x){if(!ls[x])f[x]=l[x]+w[x];else f[x]=1e18;for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;dp(y);f[x]=min(f[x],w[x]-w[y]+max(l[x],f[y]));}return;
}
signed main()
{scanf("%lld%lld",&n,&m);for(ll i=1;i<=n;i++){scanf("%lld%lld",&l[i],&w[i]);l[i]=max(l[i]-w[i],0ll);p[i]=i;}for(ll i=1;i<=m;i++){ll x,y;scanf("%lld%lld",&x,&y);G[x].push_back(y);G[y].push_back(x);}sort(p+1,p+1+n,cmp);for(ll i=1;i<=n;i++)fa[i]=i;for(ll k=1;k<=n;k++){ll x=p[k];for(ll i=0;i<G[x].size();i++){ll y=G[x][i];if(!v[y])continue;ll Fa=find(y),Fb=find(x);if(Fa==Fb)continue;fa[Fa]=Fb;w[Fb]+=w[Fa];addl(Fb,Fa);}v[x]=1;}dp(p[n]);printf("%lld\n",f[p[n]]);return 0;
}
AT4144-[ARC098D]Donation【Kruskal重构树,dp】相关推荐
- AGC002(D~F)【Kruskal重构树,博弈论,dp】
正题 AT1998 [AGC002D] Stamp Rally[Kruskal重构树,倍增] https://www.luogu.com.cn/problem/AT1998 题目大意 给出nnn个点m ...
- Network 黑暗爆炸 - 3732 倍增lca || Kruskal重构树
传送门 文章目录 题意: 思路: 题意: 思路: 两点间最长边最小值一定是最小生成树上两点间的最大值,这个比较容易证,就不多说了. 知道这个结论后, 我们直接跑一个KruskalKruskalKrus ...
- 洛谷P4768 [NOI2018]归程(Kruskal重构树)
题意 直接看题目吧,不好描述 Sol 考虑暴力做法 首先预处理出从$1$到每个节点的最短路, 对于每次询问,暴力的从这个点BFS,从能走到的点里面取$min$ 考虑如何优化,这里要用到Kruskal重 ...
- 【NOI 2018】归程(Kruskal重构树)
题面在这里就不放了. 同步赛在做这个题的时候,心里有点纠结,很容易想到离线的做法,将边和询问一起按水位线排序,模拟水位下降,维护当前的各个联通块中距离$1$最近的距离,每次遇到询问时输出所在联通块的信 ...
- kruskal 重构树(讲解 + 例题)
kruskal重构树 如何建树 模仿kruskalkruskalkruskal,先将所有边排序. 依次遍历每一条边,如果这条边的两个节点(u,vu, vu,v)不在同一个连通块里面, 则新建一个nod ...
- [ONTAK2010] Peaks加强版 (kruskal重构树+主席树+倍增)
Peaks description solution code description 在Bytemountains有N座山峰,每座山峰有他的高度h_i 有些山峰之间有双向道路相连,共M条路径,每条路 ...
- [NOI2018] 归程(线段树维护并查集的可持久化/kruskal重构树,倍增+dijkstra最短路)
[NOI2018] 归程 description solution1 code1 solution2 code description 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要 ...
- 【kruskal重构树】【主席树】werewolf 狼人(P4899)
正题 P4899 题目大意 给你一个图,对于每次询问Si,Ei,Li,RiS_i,E_i,L_i,R_iSi,Ei,Li,Ri,回答从SiS_iSi走到EiE_iEi,是否存在路径满足前面 ...
- LOJ.2865.[IOI2018]狼人(Kruskal重构树 主席树)
LOJ 洛谷 这题不就是Peaks(加强版)或者归程么..这算是\(IOI2018\)撞上\(NOI2018\)的题了? \(Kruskal\)重构树(具体是所有点按从小到大/从大到小的顺序,依次加入 ...
最新文章
- httpclient工具类,post请求发送json字符串参数,中文乱码处理
- Python遍历列表时删除元素
- linux 系统时间是在哪里记录的,Linux系统如何记录时间
- 删除360浏览器新标签页内的热词导航
- java web 颜色灰色_网站动态变灰解决方案(java web项目网站)
- UEditor 百度富文本编辑器 .Net实例
- jquery ajax 跨域解决方案 - CORS
- Leetcode-Maximum Subarray
- 基于JAVA+SpringMVC+Mybatis+MYSQL的宿舍管理平台系统
- C#窗体控件简介ListBox
- 【光学】基于matlab多缝夫琅禾费衍射【含Matlab源码 061期】
- Android简单实现图片缩略图类ThumbnailUtils
- 3月24日服务器维护公告,梦幻西游3月24日更新了什么_梦幻西游3月24日维护及系统调整公告_游戏堡...
- SqlServer 备份还原
- 龙芯cpu 3A3000搭建electron运行环境
- 区块链主要的核心内容
- UPSNet 论文笔记
- 物联网中的存储资源盘活
- 马化腾2015港大演讲。
- mysql的下载与安装
热门文章
- golang防止MySQL注入_mysql – 如何最大限度地降低golang服务中下游服务中SQL注入的风险?...
- java 非法操作异常_java – 空结果集上的非法操作
- [剑指offer]面试题34:丑数
- C++实现线段树(lazy-tag方法)-区间修改,区间查询
- UVA-11988 悲剧文本-静态链表
- protobufjs 命令执行_protobufjs简单使用
- 安卓手机 python控制_PyAndroidControl:使用python脚本控制你的安卓设备
- C语言用循环结构算平均值,C语言循环结构选择题().doc
- ubuntu 通过 海康sdk调用摄像头抓图片
- kettle同步数据中文乱码问题解决