题目描述
小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战。
游戏中有一个叫做“LCT” 的挑战,它的规则是这样子的:现在有一个N 个点的 树(Tree),每条边有一个整数边权vi ,若vi >= 0,表示走这条边会获得vi 的收益;若vi < 0 ,则表示走这条边需要支付- vi 的过路费。小L 需要控制主角Link 切掉(Cut)树上的 恰好K 条边,然后再连接 K 条边权为 0 的边,得到一棵新的树。接着,他会选择树上的两个点p; q ,并沿着树上连接这两点的简单路径从p 走到q ,并为经过的每条边支付过路费/ 获取相应收益。
海拉鲁大陆之神TemporaryDO 想考验一下Link。他告诉Link,如果Link 能切掉 合适的边、选择合适的路径从而使 总收益 - 总过路费最大化的话,就把传说中的大师之剑送给他。
小 L 想得到大师之剑,于是他找到了你来帮忙,请你告诉他,Link 能得到的 总收益 - 总过路费最大是多少。
题解
- 大爷的题解比较详细就直接上大爷的题解吧 戳戳戳
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #define ll long long 5 const int inf=1e13,N=300010; 6 struct edge { int v,w,from; }e[N<<1]; 7 int n,k,cnt,head[N]; 8 ll sum,q,l,r,ans; 9 void insert(int u,int v,int w) { e[++cnt].v=v,e[cnt].w=w,e[cnt].from=head[u],head[u]=cnt; } 10 struct data 11 { 12 int c; ll v; 13 data operator + (data d) {data a;a.v=v+d.v;a.c=c+d.c;return a;} 14 bool operator < (data d) {return v<d.v||(v==d.v&&c<d.c);} 15 }f[N][3],p[3]; 16 data be(ll v, int c) {data d;d.v=v;d.c=c;return d;} 17 data max(data a,data b) {return a<b?b:a;} 18 void dfs(int u,int fa) 19 { 20 for (int i=head[u];i;i=e[i].from) 21 { 22 int v=e[i].v; 23 if (v==fa) continue; 24 dfs(v,u),f[u][2]=max(f[u][2]+f[v][0],f[u][1]+f[v][1]+be(e[i].w-q,1)),f[u][1]=max(f[u][0]+f[v][1]+be(e[i].w,0),f[u][1]+f[v][0]),f[u][0]=f[u][0]+f[v][0]; 25 } 26 f[u][0]=max(f[u][0],max(f[u][1]+be(-q,1),f[u][2])); 27 } 28 void check(ll x) 29 { 30 q=x; 31 for (int i=1;i<=n;i++) f[i][0]=be(0,0),f[i][2]=be(-q,1),f[i][1]=be(0,0); 32 dfs(1,0),sum=f[1][0].v,cnt=f[1][0].c; 33 } 34 int main() 35 { 36 scanf("%d%d",&n,&k),k++; 37 for (int i=1,u,v,w;i<n;i++) scanf("%d%d%d",&u,&v,&w),insert(u,v,w),insert(v,u,w),r+=(w>0)?w:-w; 38 l=-r; 39 while (l<=r) 40 { 41 ll mid=(l+r)>>1; 42 check(mid); 43 if (cnt>=k) l=mid+1,ans=mid; else r=mid-1; 44 } 45 check(ans),printf("%lld",sum+k*ans); 46 }
题目描述
小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战。
游戏中有一个叫做“LCT” 的挑战,它的规则是这样子的:现在有一个N 个点的 树(Tree),每条边有一个整数边权vi ,若vi >= 0,表示走这条边会获得vi 的收益;若vi < 0 ,则表示走这条边需要支付- vi 的过路费。小L 需要控制主角Link 切掉(Cut)树上的 恰好K 条边,然后再连接 K 条边权为 0 的边,得到一棵新的树。接着,他会选择树上的两个点p; q ,并沿着树上连接这两点的简单路径从p 走到q ,并为经过的每条边支付过路费/ 获取相应收益。
海拉鲁大陆之神TemporaryDO 想考验一下Link。他告诉Link,如果Link 能切掉 合适的边、选择合适的路径从而使 总收益 - 总过路费最大化的话,就把传说中的大师之剑送给他。
小 L 想得到大师之剑,于是他找到了你来帮忙,请你告诉他,Link 能得到的 总收益 - 总过路费最大是多少。