博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
林克卡特树
阅读量:4577 次
发布时间:2019-06-08

本文共 2524 字,大约阅读时间需要 8 分钟。

/*林克卡特树首先题目可以转化为 ,从一棵树种选择k + 1条链,使得这些链上边权总和最大 可以用 dp来做,让每个点对应其父边,dp[i][j][k]表示第j个点度数为i(0, 1, 2),子树种选择了k个链的最优解这个我只能用NKK复杂度来解,因为每个点要枚举这个点选择链的个数和所有孩子 选择链的个数(但是这个经过分析复杂度是NK ?????)好吧我们不去管他, 我们要想的是 通过WQS二分去掉k的限制,这样每次就是严格On的了于是我们二分C,使得每多划分一条链都多花费C,找到恰好合适的即可至于树形dp的细节以及具体实现  我不想讲。。。 */#include
#include
#include
#include
#define M 300100#define ll long long using namespace std;struct Edge{ ll vj, ver,nxt;}edge[M << 1];ll head[M], cnt, n, k;ll L,R,mid,ans;void push(int vi, int vj, int ver){cnt++; edge[cnt].vj = vj; edge[cnt].nxt = head[vi], head[vi] = cnt; edge[cnt].ver = ver;}struct Note{ ll a,b; bool operator < (const Note &B) const {
return a == B.a ? b > B.b : a < B.a; } // 这里很奇怪 考虑最优解的最大分块情况 Note operator + (const Note &B){
return (Note){
this->a + B.a, this->b + B.b};} Note operator + (const int &B){
return (Note){
this->a + B, this->b};}}dp[3][M];Note w(Note x) {
return (Note){x.a - mid,x.b + 1};}ll read(){ ll nm = 0, f = 1; char c = getchar(); for(; !isdigit(c); c = getchar()) if(c == '-') f = -1; for(; isdigit(c); c = getchar()) nm = nm * 10 + c -'0'; return nm * f;}void dfs(int now, int fa){ dp[2][now] = max(dp[2][now],(Note){-mid, 1}); //cout << max(dp[2][1], dp[2][2]).a; for(int i = head[now]; i; i = edge[i].nxt) { int vj = edge[i].vj; if(vj == fa) continue; dfs(vj, now); dp[2][now] = max(dp[2][now] + dp[0][vj], w((dp[1][now] + dp[1][vj] + edge[i].ver))); dp[1][now] = max(dp[1][now] + dp[0][vj], (dp[0][now] + dp[1][vj] + edge[i].ver)); dp[0][now] = dp[0][now] + dp[0][vj]; } dp[0][now] = max(dp[0][now], max(w(dp[1][now]), dp[2][now])); } int main(){ n = read(), k = read() + 1; for(int i = 1; i < n; i++) { ll vi = read(), vj = read(), ver = read(); push(vi, vj, ver);push(vj, vi, ver); if(ver >= 0) R += ver; else R -= ver; } L = -R; while(L <= R) { mid = (L + R) >> 1; memset(dp, 0, sizeof(dp)); dfs(1, 0); if(dp[0][1].b <= k) R = mid - 1, ans = dp[0][1].a; else L = mid + 1; // cout << mid << " " << dp[0][1].a << "\n"; } mid = R + 1; memset(dp, 0, sizeof(dp)); dfs(1, 0);// cout << L << " !\n" << dp[0][1].b; cout << dp[0][1].a + (R + 1) * k;// cout << dp[0][1][k] + dp[0][1][k]; return 0;}/*5 31 2 12 3 -13 4 14 5 -1*/

 

转载于:https://www.cnblogs.com/luoyibujue/p/9152865.html

你可能感兴趣的文章
基于SpringBoot从零构建博客网站 - 设计可扩展上传模块和开发修改头像密码功能...
查看>>
myeclipse自动生成相应对象接收返回值的快捷键
查看>>
获取当前日期
查看>>
Python的富比较方法__le__、__ge__之间的关联关系分析
查看>>
第2课—第5节
查看>>
JavaScript简单的实例应用
查看>>
Vue.js——60分钟组件快速入门(下篇)
查看>>
【算法习作】字符串处理两例
查看>>
Day 29 _模块二 -hashlib_configparse_logging
查看>>
leetcode 19 删除链表的倒数第n个节点
查看>>
配置centos6.0为Router
查看>>
JavaScript闭包学习笔记(ife2015spring)
查看>>
Flask 初识
查看>>
工厂模式
查看>>
拦截器
查看>>
sdk
查看>>
DOM操作
查看>>
用python绘制质粒图谱
查看>>
C语言三联序列(trigraph sequences)
查看>>
luogu_1004 方格取数
查看>>