bzoj5252 [2018多省省队联测]林克卡特树

斜率优化树形dp??

我们先将问题转化成在树上选K+1条互不相交路径,使其权值和最大。

然后我们考虑60分的dp,直接维护每个点子树内选了几条路径,然后该点和0/1/2条路径相连

然后我们会发现最后的答案关于割的边数是一个单峰的函数,这时候事情就变得明朗起来个p

我们考虑拿一条斜率为k的直线去切这个函数,切到的点是什么?是每选一条路径额外付出k点代价时的最优解,于是我们二分这个斜率,然后直接树形dp求最优解以及位置即可,因为每次的最优解一定是上次的最优解和儿子的最优解共同转移而来的,所以我们只需要对每个度数维护最优解和位置即可。然后我们就可以根据dp出的位置调整斜率,然后找到答案。

这不就是wqs二分吗。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #define N 300500
 7 #define pr pair<long long,int>
 8 #define mk make_pair
 9 #define fir first
10 #define sec second
11 #define inf 0x7fffffffffffffff
12 using namespace std;
13 int e=1,head[N];
14 struct edge{
15     int v,w,next;
16 }ed[N<<1];
17 void add(int u,int v,int w){
18     ed[e].v=v;ed[e].w=w;
19     ed[e].next=head[u];head[u]=e++;
20 }
21 int n,m,K;
22 long long ans;
23 pr f[N][3],g[3],mx;
24 void add(pr &a,pr b){if(b.fir>a.fir||(b.fir==a.fir&&b.sec<a.sec))a=b;}
25 void dfs(int x,int fa){
26     f[x][0]=mk(0,0);f[x][1]=mk(-m,1);f[x][2]=mk(-inf,0);
27     for(int i=head[x];i;i=ed[i].next){
28         int v=ed[i].v;
29         if(v==fa)continue;
30         dfs(v,x);
31         g[0]=f[x][0];g[1]=f[x][1];g[2]=f[x][2];
32         mx=f[v][0];add(mx,f[v][1]);add(mx,f[v][2]);
33         add(f[x][0],mk(g[0].fir+mx.fir,g[0].sec+mx.sec));
34         add(f[x][1],mk(g[1].fir+mx.fir,g[1].sec+mx.sec));
35         add(f[x][1],mk(g[0].fir+f[v][1].fir+ed[i].w,g[0].sec+f[v][1].sec));
36         add(f[x][2],mk(g[2].fir+mx.fir,g[2].sec+mx.sec));
37         add(f[x][2],mk(g[1].fir+f[v][1].fir+ed[i].w+m,g[1].sec+f[v][1].sec-1));
38     }
39 }
40 int main(){
41     scanf("%d%d",&n,&K);
42     for(int i=1,u,v,w;i<n;i++){
43         scanf("%d%d%d",&u,&v,&w);
44         add(u,v,w);add(v,u,w);
45     }
46     int l=-1000000000,r=1000000000,mid,fin;
47     while(l<=r){
48         m=mid=(l+r)>>1;
49         dfs(1,0);
50         mx=f[1][0];add(mx,f[1][1]);add(mx,f[1][2]);
51         if(mx.sec<=K+1)fin=mid,r=mid-1;
52         else l=mid+1;
53     }
54     m=fin;
55     dfs(1,0);
56     mx=f[1][0];add(mx,f[1][1]);add(mx,f[1][2]);
57     ans=mx.fir+1ll*(K+1)*m;
58     printf("%lld\n",ans);
59     return 0;
60 }

原文地址:https://www.cnblogs.com/Ren-Ivan/p/8782360.html

时间: 2024-08-11 19:25:46

bzoj5252 [2018多省省队联测]林克卡特树的相关文章

bzoj 5249 [2018多省省队联测] IIIDX

bzoj 5249 [2018多省省队联测] IIIDX Link Solution 首先想到贪心,直接按照从大到小的顺序在后序遍历上一个个填 但是这样会有大问题,就是有相同的数的时候,会使答案不优 比如考虑 \((1, 2)(1, 3)(2, 4)\) 这样一棵树,并且点权是 \({1,1,1,2}\) 那么直接贪心会使得答案为 \(v_1=1,v_2=1,v_3=1,v_4=2\),但是实际上最优解为 \(v_1=1,v_2=1,v_3=2,v_4=1\) 问题出在我们先考虑 \(v_2\)

bzoj5248: [2018多省省队联测]一双木棋

Description 菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手.棋局开始时,棋盘上没有任何棋子, 两人轮流在格子上落子,直到填满棋盘时结束.落子的规则是:一个格子可以落子当且仅当这个格子内没有棋子且 这个格子的左侧及上方的所有格子内都有棋子. 棋盘的每个格子上,都写有两个非负整数,从上到下第i行中从左到右第j列的格子上的两个整数记作Aij.Bij.在 游戏结束后,菲菲和牛牛会分别计算自己的得分:菲菲的得分是所有有黑棋的格子上的Aij之和,牛牛的得分是所 有有白棋的格

【刷题】BZOJ 5249 [2018多省省队联测]IIIDX

Description [题目背景] Osu听过没?那是Konano最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在,他在世界知名游戏公司KONMAI内工作,离他的梦想也越来越近了.这款音乐游戏内一般都包含了许多歌曲,歌曲越多,玩家越不易玩腻.同时,为了使玩家在游戏上氪更多的金钱花更多的时间,游戏一开始一般都不会将所有曲目公开,有些曲目你需要通关某首特定歌曲才会解锁,而且越晚解锁的曲目难度越高. [题目描述] 这一天,Konano接到了一个任务,他需要给正在制作中的

【刷题】BZOJ 5248 [2018多省省队联测]一双木棋

Description 菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手.棋局开始时,棋盘上没有任何棋子, 两人轮流在格子上落子,直到填满棋盘时结束.落子的规则是:一个格子可以落子当且仅当这个格子内没有棋子且 这个格子的左侧及上方的所有格子内都有棋子. 棋盘的每个格子上,都写有两个非负整数,从上到下第i行中从左到右第j列的格子上的两个整数记作Aij.Bij.在 游戏结束后,菲菲和牛牛会分别计算自己的得分:菲菲的得分是所有有黑棋的格子上的Aij之和,牛牛的得分是所 有有白棋的格

5249: [2018多省省队联测]IIIDX

Description [题目背景] Osu听过没?那是Konano最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在,他在世界知名游戏公司KONMAI内工作,离他的梦想也越来越近了.这款音乐游戏内一般都包含了许多歌曲,歌曲越多,玩家越不易玩腻.同时,为了使玩家在游戏上氪更多的金钱花更多的时间,游戏一开始一般都不会将所有曲目公开,有些曲目你需要通关某首特定歌曲才会解锁,而且越晚解锁的曲目难度越高. [题目描述] 这一天,Konano接到了一个任务,他需要给正在制作中的

bzoj千题计划307:bzoj5248: [2018多省省队联测]一双木棋

https://www.lydsy.com/JudgeOnline/problem.php?id=5248 先手希望先手得分减后手得分最大,后手希望先手得分减后手得分最小 棋盘的局面一定是阶梯状,且从上往下递减 可以将轮廓线作为状态,记忆化搜索 用n个数表示一个状态,第i个数表示第i行放了几个 记忆的状态表示当棋盘为这个状态时,接下来再下的最有解 记忆化搜索节省的是接下来再下的时间 #include<map> #include<cstdio> #include<cstring

BZOJ 5248: [2018多省省队联测]一双木棋

Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 439  Solved: 379[Submit][Status][Discuss] Description 菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手.棋局开始时,棋盘上没有任何棋子, 两人轮流在格子上落子,直到填满棋盘时结束.落子的规则是:一个格子可以落子当且仅当这个格子内没有棋子且 这个格子的左侧及上方的所有格子内都有棋子. 棋盘的每个格子上,都写有两个非负整数,从上到下

【HEOI 2018】林克卡特树

先说60分的.思路题解上很清晰: 问题似乎等价于选K+1条点不相交的链哎!F(x,k,0/1/2)表示考虑以x为根的子树,选了k条链,点x的度数为0/1/2的最优解. 我说一下比较坑的地方吧:1.初始化要-Inf(反正我不加这个会wa)2.注意转移的顺序3.别忘了突然出现新的路径或者突然消失了一个路径的时侯加减14.一定要割k下细节说多不多,说少不少,还得自己打.说一下100分的.60分的瓶颈在于k,那么如果对于k没有限制的话,那么我们的转移就会变成O(n)的(和60分的dp是差不多的).如何去

[八省联考2018]林克卡特树lct

#include<bits/stdc++.h> #define RG register #define IL inline #define _ 500005 #define INF 1e18 #define ll long long using namespace std; IL ll gi(){ RG ll data = 0 , m = 1; RG char ch = 0; while(ch != '-' && (ch<'0' || ch > '9')) ch =