正题

题目链接: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. vim宏录制

    宏录制 当你要重复某一个操作时,录制的宏可以很快地帮你完成任务. 准备文本 <!DOCTYPE html> <html lang="en"> <hea ...

  2. mfc HackerTools全局钩子

    钩子英文名叫Hook,是一种截获windows系统中某应用程序或者所有进程的消息的一种技术. 如在键盘中按下一键,操作系统将收到键按下消息,把消息放入消息队列,然后消息队列对消息进行派发,发给相应的应 ...

  3. [ASP.NET MVC]@Scripts.Render、@Styles.Render的使用

    一.配置BundleConfig.cs文件 1.首先要在App_Start 里面BundleConfig.cs 文件里面 添加要包含的css文件 2.BundleConfig就是一个微软新加的 一个打 ...

  4. java8 lambda 表达式详解

    lambada 表达式实质上是一个匿名方法,但该方法并非独立执行,而是用于实现由函数式接口定义的唯一抽象方法 使用 lambda 表达式时,会创建实现了函数式接口的一个匿名类实例 可以将 lambda ...

  5. SpringMVC IO 文件上传

    1 public class FileUtil { 2 3 4 /** 5 * 读取文件内容,作为字符串返回 6 */ 7 public static String readFileAsString( ...

  6. springboot静态资源路径制定

    spring.resources.static-location参数指定了Spring Boot-web项目中静态文件存放地址, 该参数默认设置为: classpath:/static, classp ...

  7. Data Augmentation

    常见操作: 水平翻转-Horizontal Flip Scale-亮度变化 透视变换-perspective,旋转-rotation,错切-Shear,仿射-affine等 尺寸变幻-Resize,可 ...

  8. iGuard和NFS文件同步的解决方案

    一般来说,从文件系统中获得文件变化信息,调用操作系统提供的 API 即可.Windows 操作系统上有个名为 ReadDirectoryChangesW 的 API 接口,只要监视一个目录路径就可以获 ...

  9. MySQL-SQL基础-DCL

    mysql> grant select,insert on sakila.* to 'zl'@'localhost' identified by '123'; Query OK, 0 rows ...

  10. DNS重新绑定攻击

    来自微信外挂的安全风险 DNS重新绑定攻击 DDNS 动态域名设置