正题

luogu 7600[APIO 2021 T3]
luogu-CF1119F


题目大意

给你一棵树,给出每条边割掉的代价,问你对于0⩽k<n0\leqslant k<n0⩽k<n,使得每个点的度数小于k的最小代价


解题思路

首先考虑单询问的情况

可以设fx,1/0f_{x,1/0}fx,1/0​表示第x个点到父节点的边连/不连的最小代价

对于点x,最多连k个点,那么要割掉至少degx−kdeg_x-kdegx​−k个点

假设所有子节点都连,计算出割掉某个子节点的连边的代价(从连到不连,−fson,1+fson,0+len-f_{son,1}+f_{son,0}+len−fson,1​+fson,0​+len),然后从中选择degx−kdeg_x-kdegx​−k个最小代价的点(如果割掉更优则尽量割),该操作可以用堆实现

当k较大时,不难发现,很多点已经满足deg⩽kdeg\leqslant kdeg⩽k的条件,没有计算的意义

所以对于点x(degx⩽kdeg_x\leqslant kdegx​⩽k),x已经满足条件,所以不用管该点,然后在连接的点中加上该点(对于这些点还有意义)

对于每个点,可以用两个堆维护一个可删堆,对于deg>kdeg>kdeg>k的点,用完后要删掉(下一轮中数值会改变),而对于deg⩽kdeg\leqslant kdeg⩽k的点,,为数值不会改变,所以不删

综上,每轮将无用的点删掉,然后计算有用的点


代码

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 500010
using namespace std;
ll n, w, h, ans, summ;
ll p[N], s[N], f[N][2], gt[N], addl[N], dell[N], deg[N];
struct lne
{ll x, y, z;
}l[N];
struct rec
{ll to, l;
};
vector<rec>a[N];
bool cmp(lne x, lne y)
{return deg[x.y] > deg[y.y];
}
bool cmpp(ll x, ll y)
{return deg[x] < deg[y];
}
struct heap//可删堆
{priority_queue<int>d1, d2;ll sum;ll sz(){return d1.size() - d2.size();}void clear(){while(d1.size() && d2.size() && d1.top() == d2.top())d1.pop(), d2.pop();return;}void add(ll x){d1.push(x);sum += x;return; }void del(ll x){d2.push(x);sum -= x;clear();return;}void pop(){sum -= d1.top();d1.pop();clear();return;}ll top(){ll g = d1.top();pop();return g;}
}d[N];
void dfs(ll x, ll fa, ll k)
{p[x] = k;f[x][0] = f[x][1] = 0;for (int i = 0; i < a[x].size(); ++i){ll y = a[x][i].to;if (deg[y] <= k) break;if (y != fa)dfs(y, x, k);}ll an = 0, dn = 0, num = deg[x] - k;while(d[x].sz() > num) d[x].pop();for (int i = 0; i < a[x].size(); ++i){ll y = a[x][i].to, z = a[x][i].l;if (deg[y] <= k) break;if (y != fa){if (f[y][1] < f[y][0] + z)//计算代价{f[x][1] += f[y][1];d[x].add(-f[y][1] + f[y][0] + z);dell[++dn] = -f[y][1] + f[y][0] + z;}else num--, f[x][1] += f[y][0] + z;//代价小于1的就直接删,而且要删的边少一条}}f[x][0] = f[x][1];while(d[x].sz() > max(num, 0ll))//已经删的边可能大于要删的边,所以要取maxaddl[++an] = d[x].top();f[x][1] += d[x].sum;while(d[x].sz() > max(num - 1, 0ll))addl[++an] = d[x].top();f[x][0] += d[x].sum;for (int i = 1; i <= an; ++i)d[x].add(addl[i]);//补回去for (int i = 1; i <= dn; ++i)d[x].del(dell[i]);return;
}
int main()
{scanf("%lld", &n);for (ll i = 1; i < n; ++i){w++;scanf("%lld%lld%lld", &l[w].x, &l[w].y, &l[w].z);w++;l[w] = l[w - 1];swap(l[w].x, l[w].y);deg[l[w].x]++;deg[l[w].y]++;summ += l[w].z;}for (ll i = 1; i <= n; ++i)s[i] = i;sort(l + 1, l + 1 + w, cmp);//边从小到大排,当枚举一个点的连边时,如果度数小于等于k,那么接下来的点都没有意义sort(s + 1, s + 1 + n, cmpp);for (ll i = 1; i <= w; ++i)a[l[i].x].push_back((rec){l[i].y, l[i].z});printf("%lld", summ);h = 1;for (ll k = 1; k < n; ++k){ans = 0;while(deg[s[h]] <= k && h <= n)//没用的点删掉{for (ll i = 0; i < a[s[h]].size(); ++i)if (deg[a[s[h]][i].to] > k)d[a[s[h]][i].to].add(a[s[h]][i].l);else break;h++;}for (ll i = h; i <= n; ++i)if (p[s[i]] < k){dfs(s[i], 0, k);ans += f[s[i]][1];}printf(" %lld", ans);}return 0;
}

【堆】【DP】Niyaz and Small Degrees(luogu 7600[APIO 2021 T3]/luogu-CF1119F)相关推荐

  1. 【倍增】【线段树】雨林跳跃(luogu 7599[APIO 2021 T2])

    正题 luogu 7599[APIO 2021 T2] 题目大意 给你一排树中每棵树的高度,每次跳跃可以跳到左/右边第一棵比该树高的树,问你从A-B中某棵树跳到C-D中的某棵树的最小步数(A⩽B< ...

  2. 【BZOJ-4524】伪光滑数 堆 + 贪心 (暴力) [可持久化可并堆 + DP]

    4524: [Cqoi2016]伪光滑数 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 183  Solved: 82 [Submit][Statu ...

  3. P7600-[APIO2021]封闭道路【堆,dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P7600 题目大意 给出nnn个点的一棵树,边有边权,对于每个kkk求去掉最小边权和的点使得每个点的度数都不超过kk ...

  4. 【DP】建学校问题(luogu 2803/2018 特长生 T3)

    正题 luogu 2803 题目大意 给出n个点,和相邻的点的距离,每个点有一个权值,现在让你建k个特殊点,使所有点到其中一个特殊点的代价之和最小 解题思路 先预处理处一个区间到同一个特殊点的最小代价 ...

  5. 【DP】【树状数组】免费馅饼(luogu 7302/金牌导航 数据结构优化DP-4)

    正题 luogu 7302 金牌导航 数据结构优化DP-4 题目大意 在坐标轴上会出现n个金币,第i个金币tit_iti​时在wiw_iwi​出现(只出现一个单位时间),价值为sis_isi​,当你t ...

  6. Luogu 3642 [APIO 2016] 烟火表演

    传送门 引例(上一道题) 凸函数 一开始的思路 正解 参考代码 总结 传送门 引例(上一道题) 凸函数   回忆我们上一道题是怎么做的.我们维护的东西的实质是一个(下)凸函数.由于我们的操作相当于是加 ...

  7. Luogu 3645 [APIO 2015] 雅加达的摩天楼

    传送门 思路 正解 参考代码 Update 传送门 思路   唉,我太弱了,我都看出来要分块了,就是做不来.不过终于把题读对了.   先来看子任务三怎么做.显然可以有一个 O(m2) O ( m 2 ...

  8. BZOJ 1799 [Ahoi2009] self 同类分布(数位DP)【BZOJ千题计划(quexin】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/1799(样例时限设置有问题,应该为 2 ...

  9. acwing基础课——堆

    由数据范围反推算法复杂度以及算法内容 - AcWing 常用代码模板2--数据结构 - AcWing 基本思想: 如果有一个关键码的集合K = {k0,k1, k2,-,kn-1},把它的所有元素按完 ...

最新文章

  1. GraphQL 入门第一篇
  2. ubuntu在不重装系统情况下关于调整分区,或是从现有根目录划分/home等分区
  3. 币对交易所_比特币向1万4大涨,OK交易所的比特币为什么反而贬值7折?
  4. 《大话》之 策略模式 Vs 状态模式
  5. POJ 1017 Packets【贪心】
  6. 准备创建一个自己的校验提示Extender
  7. 头衔的权威暗示影响力
  8. M70仿真系统软件下载和使用
  9. Vivado保姆级安装
  10. Comsol 2020全套教学视频 教程入门讲解新手的福音
  11. 【历史上的今天】10 月 10 日:谷歌推出 Dart 预览版;俄罗斯最大的社交网站上线;上海大众汽车公司诞生
  12. 何钦铭c语言第三版第9章答案,c语言程序设计第3版何钦铭 颜 晖 第9章 结构.pdf...
  13. webstorm-主题和配色
  14. jmeter利用取样器中http发送请求(2)·
  15. flash 在firebox/IE中 提示安装 浏览器是否有flash插件
  16. 汽车自动变速器的控制技术
  17. python字典方法有三种_介绍三种访问字典的方法
  18. 运筹学基础【五】 之 线性规划
  19. QNX Neutrino IPL
  20. 限流算法-常见的4种限流算法

热门文章

  1. 乐视android版本点四下,EUI5.9+Android7.0刷机包
  2. zipsys驱动签名工具_全球首发 300系列主板USB WIN7 64位驱动 SMXDIY
  3. 蓝桥杯2015初赛-奖券数目-枚举
  4. 使用单项循环链表实现字典操作(算法导论第十章10.2-5题)
  5. 家居灯光控制系统设计 android,基于Android的室内照明控制系统设计与实现
  6. 记一次应用配置的数据库连接被打满问题
  7. L. Continuous Intervals(单调栈 + 线段树 + 思维)
  8. P3899 [湖南集训]谈笑风生(线段树合并)
  9. Codeforces Round #588 (Div. 2) D. Marcin and Training Camp 思维
  10. Codeforces Round #619 (Div. 2) D. Time to Run 矩阵回路构造