[codeforces contest 1119 F] Niyaz and Small Degrees 解题报告 (树形DP+堆)
interlinkage:
http://codeforces.com/contest/1119/problem/F
description:
有一颗$n$个节点的树,每条边有一个边权
对于一个$x$,删去一些边使得每个点的度数都不超过$x$,最小化删去边的边权并输出
需要一次输出$x=0->n-1$的值
$1<=n<=250000$
solution:
- part1
- 先考虑单个$x$的做法。任选一个根,设$f_{u,0/1}$表示以节点$u$为根的子树内,节点$u$与它的父亲不断/断的最小代价;
- 显然这个可以讨论转移,但我们换一个更好的角度;
- 设$v$为$u$的一个儿子,若$f_{v,1}+c<=f_{v,0}$,即断的话比不断更优秀的,那么我们一定选择断,因为这样还可以让$u$的度数小$1$。这种情况我们就直接加上$f_{v,1}+c$,并让$u$度数$--$;
- 否则的话我们就先假设这条边不断,加上$f_{v,0}$。那么到最后可能会发现$u$的度数不满足不超过$x$,显然我们要把若干个$f_{v,0}$变成$f_{v,1}+c$;
- 我们对每个点维护一个$f_{v,1}+c-f_{v,0}$的堆,取度数-$x$个最小的就好了;
- 这里的堆本质上维护的就是通过多大的代价能让度数减一;
- part2
- 现在考虑多个$x$,从小做到大
- 有一个很显然的想法,若是一个点原来的度数就不超过$x$,那么这个点可以直接删掉;
- 做法是把所有以这个点为端点的边放到这些边的另一个端点的堆里面,表示可以通过断掉这条边来使得度数减一;
- 剩下的就是对所有有用的点,即度数大于$x$的点做上面的$DP$就好了;
- part3
- 复杂度显然为$\sum_{x=0}^{n-1}\sum_{i=1}^{n}[du_i>x]=\sum_{i=1}^{n}du_i=O(n)$;
code:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#define fi first
#define se second
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll; const ll N=;
ll n;
ll du[N],nxt[N],vis[N];
ll sum[N];
vector <pll> e[N];
vector <ll> d[N];
inline ll read()
{
char ch=getchar();ll s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
bool cmp(pll x,pll y) {return du[x.fi]<du[y.fi];}
struct node
{
priority_queue <ll> A,B;
void push(ll x) {A.push(x);}
void del(ll x) {B.push(x);}
ll top() {while (!B.empty()&&A.top()==B.top()) A.pop(),B.pop();return A.top();}
void pop() {top();A.pop();}
ll size() {return A.size()-B.size();}
}h[N];
void upd(ll x,ll num)
{
while (h[x].size()>num)
{
sum[x]=sum[x]-h[x].top();
h[x].pop();
}
}
void upd1(ll x,ll num,vector <ll> &add)
{
while (h[x].size()>num)
{
sum[x]=sum[x]-h[x].top();
add.pb(h[x].top());
h[x].pop();
}
}
void dele(ll x)
{
vis[x]=;
for (ll i=;i<e[x].size();i++)
{
ll y=e[x][i].fi,c=e[x][i].se;;
if (vis[y]) continue;
h[y].push(c);sum[y]=sum[y]+c;
}
}
ll D;
ll f[N][],st[N];
void dfs(ll x)
{
vis[x]=;ll num=du[x]-D;
upd(x,num);
vector <ll> add,del;
add.clear();del.clear();
ll siz=e[x].size(),tot=;
while (st[x]<siz&&du[e[x][st[x]].fi]<=D) st[x]++;
for (ll i=st[x];i<siz;i++)
{
ll y=e[x][i].fi,c=e[x][i].se;;
if (vis[y]) continue;
dfs(y);
if (f[y][]+c<=f[y][]) {num--;tot=tot+f[y][]+c;}
else
{
tot=tot+f[y][];
ll o=f[y][]+c-f[y][];
del.pb(o);
h[x].push(o);
sum[x]=sum[x]+o;
}
}
upd1(x,max(0ll,num),add);
f[x][]=tot+sum[x];
upd1(x,max(0ll,num-),add);
f[x][]=tot+sum[x];
for (ll i=;i<add.size();i++) h[x].push(add[i]),sum[x]+=add[i];
for (ll i=;i<del.size();i++) h[x].del(del[i]),sum[x]-=del[i];
}
int main()
{
n=read();
ll ans=;
for (ll i=;i<n;i++)
{
ll x=read(),y=read(),c=read();
e[x].pb({y,c});e[y].pb({x,c});
du[x]++;du[y]++;
ans+=c;
}
printf("%I64d ",ans);
for (ll i=;i<=n;i++)
{
d[du[i]].pb(i);
sort(e[i].begin(),e[i].end(),cmp);
}
nxt[n]=n+;
for (ll i=n-;i>=;i--)
{
if (d[i+].size()) nxt[i]=i+;
else nxt[i]=nxt[i+];
}
memset(vis,,sizeof(vis));
for (ll u=;u<n;u++)
{
for (ll i=;i<d[u].size();i++) dele(d[u][i]);
ans=;D=u;
for (ll i=u+;i<n;i=nxt[i])
for (ll j=;j<d[i].size();j++)
{
if (vis[d[i][j]]) continue;
dfs(d[i][j]);
ans=ans+f[d[i][j]][];
}
for (ll i=u+;i<n;i=nxt[i])
for (ll j=;j<d[i].size();j++) vis[d[i][j]]=;
printf("%I64d ",ans);
}
return ;
}
[codeforces contest 1119 F] Niyaz and Small Degrees 解题报告 (树形DP+堆)的更多相关文章
- 【codeforces contest 1119 F】Niyaz and Small Degrees
题目 描述 \(n\) 个点的树,每条边有一个边权: 对于一个 \(X\) ,求删去一些边后使得每个点的度数 \(d_i\) 均不超过 \(X\) 的最小代价: 你需要依次输出 \(X=0 \to n ...
- 树形DP ---- Codeforces Global Round 2 F. Niyaz and Small Degrees引发的一场血案
Aspirations:没有结果,没有成绩,acm是否有意义?它最大的意义就是让我培养快速理解和应用一个个未知知识点的能力. ————————————————————————————————————— ...
- Codeforces Round #384 (Div. 2)D - Chloe and pleasant prizes 树形dp
D - Chloe and pleasant prizes 链接 http://codeforces.com/contest/743/problem/D 题面 Generous sponsors of ...
- Codeforces Round #551 (Div. 2) D. Serval and Rooted Tree (树形dp)
题目:http://codeforces.com/contest/1153/problem/D 题意:给你一棵树,每个节点有一个操作,0代表取子节点中最小的那个值,1代表取子节点中最大的值,叶子节点的 ...
- Codeforces Round #419 (Div. 2) E. Karen and Supermarket(树形dp)
http://codeforces.com/contest/816/problem/E 题意: 去超市买东西,共有m块钱,每件商品有优惠卷可用,前提是xi商品的优惠券被用.问最多能买多少件商品? 思路 ...
- 2017 Multi-University Training Contest - Team 1 1003&&HDU 6035 Colorful Tree【树形dp】
Colorful Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)T ...
- 2015 Multi-University Training Contest 6 solutions BY ZJU(部分解题报告)
官方解题报告:http://bestcoder.hdu.edu.cn/blog/2015-multi-university-training-contest-6-solutions-by-zju/ 表 ...
- codeforces 519C. A and B and Team Training 解题报告
题目链接:http://codeforces.com/contest/519/problem/C 题目意思:给出 n 个 experienced participants 和 m 个 newbie ...
- codeforces 454B. Little Pony and Sort by Shift 解题报告
题目链接:http://codeforces.com/problemset/problem/454/B 题目意思:给出一个序列你 a1, a2, ..., an. 问每次操作只能通过将最后一个数拿出来 ...
随机推荐
- ICCV2015上的GazeTracker论文总结
SLAM问题先慢慢编译一段时间,赶紧拾起来GazeTrack的事情...... ICCV2015的大部分paper已经可以下载,文章列表在这个位置. http://www.cvpapers.com/i ...
- ASP.NET 页面验证cookie
using System; using System.Collections.Generic; using System.Linq; using System.Web; /// <summary ...
- jquery.datatable.js实际运用
$.dataTablesSettings = { deferRender: true,// 当处理大数据时,延迟渲染数据,有效提高Datatables处理能力 bStateSave: true,//表 ...
- cocos creator 底部按钮touch延迟
cocos论坛里有这个问题: http://forum.cocos.com/t/ios-touchstart-bug/63367我的引擎版本:"engine_version": & ...
- 前端面试题总结 -vue
1.active-class是哪个组件的属性? vue-router模块的router-link组件. 2.嵌套路由怎么定义? 在 VueRouter 的参数中使用 children 配置,这样就可以 ...
- rabbitmq和kafka的区别
1.吞吐量kafka吞吐量更高: 1)Zero Copy机制,内核copy数据直接copy到网络设备,不必经过内核到用户再到内核的copy,减小了copy次数和上下文切换次数,大大提高了效率. 2)磁 ...
- 15.5.5 【Task实现细节】围绕 await 表达式的控制
任何 await 表达式均表示执行路径的一个分支.首先,被等待的异步操作得到一个awaiter,然后检查其 IsCompleted 属性.若返回 true ,即可立即获得结果并继续.否则,需进行以下处 ...
- android apk的签名和权限问题
一. android apk的签名问题(http://blog.csdn.net/lyq8479/article/details/6401093) 1.为什么要给Android应用程序签名? ...
- HTTP 下载文件中文文件名在 Firefox 下乱码问题
转自:http://www.imhdr.com/991/ HTTP 下载文件,中文文件名在 Firefox 下乱码问题 最近帮助一同事解决 HTTP 下载文件时,中文文件名在 Firefox 下乱码的 ...
- P1040 加分二叉树(树上记忆化搜素)
这道题很水 但我没做出来……………………………… 我写的时候状态设计错了,设计dp[l][m][r]为从l到r以m为根的值 这样写遍历状态就是n^3的,会TLE. 而且写路径的时候是用结构体写的,这样 ...