正题

题目链接:https://www.luogu.com.cn/problem/P7600


题目大意

给出\(n\)个点的一棵树,边有边权,对于每个\(k\)求去掉最小边权和的点使得每个点的度数都不超过\(k\)。

\(1\leq n\leq 10^5\)


题目大意

APIO遇到的原题,和CF1119F一样,感觉要被冲烂。

先考虑暴力的做法,设\(f_{i,0/1}\)表示点\(i\)割不割连接父节点的边时满足子树条件的最小代价,然后对于每个点把每个儿子割掉的代价排个序取最小的一部分就好了,这样时间复杂度\(O(n^2)\)的。

然后优化的话,发现当\(k\)比较大时有很大一部分的点是没有作用的,所以可以考虑删除一些没有用的点。度数小于等于\(k\)的点直接删去,这样的话如果我们就能做到枚举每个没有被删去的点,因为所有点的度数和为\(2n\),这样的复杂度是\(O(n)\)的。

删除的点我们把代价加入父节点处维护的一个堆中,然后每次取出前一部分的点就好了,时间复杂度\(O(n\log n)\)。


还是贴CF那题的代码吧,APIO的那个东西好丑(

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#define ll long long
#define mp(x,y) make_pair(x,y)
using namespace std; const ll N=3e5+10; struct Heap{
priority_queue<ll> q1,q2;ll sum;
void Push(ll x){q1.push(x);sum+=x;return;}
void Pop(ll x){q2.push(x);sum-=x;return;}
ll Top(){
while(!q2.empty()&&q1.top()==q2.top())
q1.pop(),q2.pop();
ll w=q1.top();q1.pop();sum-=w;
return w;
}
ll Size(){return q1.size()-q2.size();}
}q[N];
struct node{
ll to,next,w;
}a[N<<1];
ll n,tot,deg[N],f[N][2],ls[N],p[N],v[N];
set<pair<ll,ll> > s[N];queue<ll> cl,del;vector<ll> ans; void addl(ll x,ll y,ll w){
a[++tot].to=y;deg[y]++;
a[tot].next=ls[x];a[tot].w=w;
ls[x]=tot;return;
}
void dfs(ll x,ll fa,ll k){
f[x][0]=f[x][1]=0;v[x]=k;ll siz=deg[x],S=0;
while(q[x].Size()>siz-k)q[x].Top();
set<pair<ll,ll> >::iterator it;
for(it=s[x].begin();it!=s[x].end();it++){
ll y=(*it).first;
if(y==fa)continue;
dfs(y,x,k);
}
for(it=s[x].begin();it!=s[x].end();it++){
ll y=(*it).first;
if(y==fa)continue;
ll w=f[y][1]-f[y][0]+(*it).second;
if(w<=0){S+=f[y][1]+(*it).second;siz--;continue;}
S+=f[y][0];q[x].Push(w);del.push(w);
}
while(q[x].Size()>max(siz-k,0ll)){
ll w=q[x].Top();
cl.push(w);
}
f[x][0]=S+q[x].sum; while(q[x].Size()>max(siz-k-1,0ll)){
ll w=q[x].Top();
cl.push(w);
}
f[x][1]=S+q[x].sum; while(!cl.empty())q[x].Push(cl.front()),cl.pop();
while(!del.empty())q[x].Pop(del.front()),del.pop();
return;
}
bool cmp(ll x,ll y)
{return deg[x]<deg[y];}
signed main(){
scanf("%lld",&n);
for(ll i=1;i<n;i++){
ll x,y,w;
scanf("%lld%lld%lld",&x,&y,&w);
addl(x,y,w);addl(y,x,w);
s[x].insert(mp(y,w));
s[y].insert(mp(x,w));
}
for(ll i=1;i<=n;i++)p[i]=i;
sort(p+1,p+n+1,cmp);
ll z=1;
memset(v,-1,sizeof(v));
for(ll k=0;k<n;k++){
if(k>=deg[p[n]]){
ans.push_back(0);
continue;
}
while(z<=n&&deg[p[z]]<=k){
ll x=p[z];
for(ll i=ls[x];i;i=a[i].next)
if(deg[a[i].to]>k){
q[a[i].to].Push(a[i].w);
s[a[i].to].erase(mp(x,a[i].w));
}
z++;
}
ll sum=0;
for(ll i=z;i<=n;i++)
if(v[p[i]]!=k)dfs(p[i],-1,k),sum+=f[p[i]][0];
ans.push_back(sum);
}
for(ll i=0;i<ans.size();i++)
printf("%lld ",ans[i]);
}

P7600-[APIO2021]封闭道路【堆,dp】的更多相关文章

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

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

  2. 重建道路 树形DP

    重建道路 树形DP 给一棵树,问最少断多少边使得这棵树树最终只有\(p​\)个节点 设计dp状态\(f[u][i][j]\)表示节点\(u\),到第\(i\)个儿子,使\(j\)个节点分离,但是不分离 ...

  3. 洛谷 P1070 道路游戏 DP

    P1070 道路游戏 题意: 有一个环,环上有n个工厂,每个工厂可以生产价格为x的零钱收割机器人,每个机器人在购买后可以沿着环最多走p条边,一秒走一条,每条边不同时间上出现的金币是不同的,问如何安排购 ...

  4. [BZOJ 2500]幸福的道路 树形dp+单调队列+二分答案

    考试的时候打了个树链剖分,而且还审错题了,以为是每天找所有点的最长路,原来是每天起点的树上最长路径再搞事情.. 先用dfs处理出来每个节点以他为根的子树的最长链和次长链.(后面会用到) 然后用类似dp ...

  5. bzoj2500幸福的道路 树形dp+单调队列

    2500: 幸福的道路 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 434  Solved: 170[Submit][Status][Discuss ...

  6. [HNOI2018]道路 --- 树形DP

    [HNOI2018]道路 题目描述: W 国的交通呈一棵树的形状.W 国一共有 \(n-1\) 个城市和 \(n\) 个乡村, 其中城市从 \(1\) 到 \(n-1\) 编号,乡村从 \(1\) 到 ...

  7. JZYZOJ1525 HAOI2012道路 堆优化的dijkstra+pair

    From Tyvj Guest ☆[haoi2012]道路                 描述 Description     C国有n座城市,城市之间通过m条单向道路连接.一条路径被称为最短路,当 ...

  8. 【bzoj2500】幸福的道路 树形dp+单调队列

    Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图. ...

  9. 【bzoj2500】幸福的道路 树形dp+倍增RMQ+二分

    原文地址:http://www.cnblogs.com/GXZlegend/p/6825389.html 题目描述 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一 ...

随机推荐

  1. ES6中新增的数组知识记录

    JSON数组格式转换 let json = { '0': 'hello', '1': 'I am ', '2': 'michael', length:3 } 这就是一个JSON数组格式,跟普通的JSO ...

  2. mpvue学习笔记

    坑一: 挂载在Vue.prototype上的属性,在模板语法里面是undefined,必须经过computed计算过一下才能用. 坑二: 关于生命周期钩子 因为小程序的历史页面不会销毁,所以在生命周期 ...

  3. HCNP Routing&Switching之OSPF网络类型

    前文我们了解了PPPoE协议相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15182512.html:今天我们聊聊一聊OSPF中的网络类型相关话题: ...

  4. .NET Core:在ASP.NET Core WebApi中使用Cookie

    一.Cookie的作用 Cookie通常用来存储有关用户信息的一条数据,可以用来标识登录用户,Cookie存储在客户端的浏览器上.在大多数浏览器中,每个Cookie都存储为一个小文件.Cookie表示 ...

  5. javaWeb常用面试题

    JDBC JDBC访问数据库的基本步骤是什么? 加载驱动 通过DriverManager对象获取连接对象Connection 通过连接对象获取会话,有2种方式Statement.PreparedSta ...

  6. 查看node.js全局安装的插件路径

    查看 npm  全局插件 默认全局安装路径 参考:https://www.jianshu.com/p/f2873fcef5aa 首先 nodejs安装好之后,默认情况下会有如下配置 npm confi ...

  7. 微信小程序学习笔记四 页面的生命周期

    1. 生命周期 1.1 对应阶段说明 onLOad(Object query) 1.1 页面加载时触发, 一个页面只会调用一次, 可以在 onLoad的参数中获取打开当前页面路径中的参数 1.2 参数 ...

  8. uni-app 小程序从零开始的开发流程

    前言 本文基于 HBuilderX 3.1.22 + 微信开发者工具 1.05.2106300为主要内容进行说明. 文档版本:1.0.0 更新时间:2021-09-03 15:32 一.准备 uni- ...

  9. constexpr-C++11

    constexpr和常量表达式 常量表达式(const expression)是指值不会改变并且在编译过程就能得到计算结果的表达式.显然,字面值属于常量表达式,用常量表达式初始化的const对象也是常 ...

  10. Python文件(File)及读写操作及生成器yield

    open函数在内存中创建缓存区,将磁盘上的内容复制到此处.文件内容读入到文件对象缓冲区后,文件对象将缓冲区视为非常大的列表,其中每个元素都有一个索引.文件对象按字节(大约每个字符)来对文件对象缓冲区索 ...