https://www.luogu.com.cn/problem/P3647

我写DP像cxk

发现只有两种连边的方式

假设最优的策略已经给了出来,那么一定存在选定某个点为根的时候,只存在第一种脸边的情况

于是跑换根DP即可

具体的话设f[u][0/1]f[u][0/1]f[u][0/1]表示uuu是否作为中间点uuu往上延伸,的最大得分

转移还是挺显然的

f[u][0]=∑v∈sonmax⁡(f[v][0],f[v][1]+w[v])f[u][0]=\sum\limits_{v\in son} \max(f[v][0],f[v][1]+w[v])f[u][0]=v∈son∑​max(f[v][0],f[v][1]+w[v])
w[v]w[v]w[v]表示fa[u]−>ufa[u]->ufa[u]−>u的边权

f[u][1]=f[u][0]+max⁡(w[v]+f[v][0]−max⁡(f[v][0],f[v][1]+w[v]))f[u][1]=f[u][0]+\max(w[v]+f[v][0] - \max(f[v][0],f[v][1]+w[v]))f[u][1]=f[u][0]+max(w[v]+f[v][0]−max(f[v][0],f[v][1]+w[v]))
就是把上面vvv的贡献max⁡(f[v][0],f[v][1]+w[v])\max(f[v][0],f[v][1]+w[v])max(f[v][0],f[v][1]+w[v])挖掉,然后加上vvv作为起点 往上延伸的贡献w[v]+f[v][0]w[v]+f[v][0]w[v]+f[v][0]

换根看起来不太好换

f[u][1]f[u][1]f[u][1]因为涉及到最大值,所以要记录uuu的 儿子中的最大值和次大值

考虑换根转移

设ls[u][0/1]ls[u][0/1]ls[u][0/1]表示图中圈出来的那蓝色部分,那ls[fa][0/1]ls[fa][0/1]ls[fa][0/1]表示的就是图中圈起来的绿色部分

因为f[u][1]f[u][1]f[u][1]转移维护最大值的时候没有维护到父亲的转移,所以要用ls[fa]ls[fa]ls[fa]来重新更新一下ls[u]ls[u]ls[u]

然后设g[u][0]g[u][0]g[u][0]表示以uuu为根的答案

然后按照上面说的转移即可

具体实现看代码吧

code:

#include<bits/stdc++.h>
#define N 400050
#define ll long long
using namespace std;
struct edge {int v, nxt, c;
} e[N << 1];
int p[N], eid;
void init() {memset(p, -1, sizeof p);eid = 0;
}
void insert(int u, int v, int c) {e[eid].v = v;e[eid].c = c;e[eid].nxt = p[u];p[u] = eid ++;
}const ll inf = 1e18;
ll ma1[N], ma2[N], f[N][2], g[N][2], ls[N][2], w[N];
int son1[N], son2[N], n;
void dfs(int u, int fa) {ma1[u] = ma2[u] = - inf, son1[u] = son2[u] = 0;for(int i = p[u]; i + 1; i = e[i].nxt) {int v = e[i].v, c = e[i].c;if(v == fa) continue; w[v] = c;dfs(v, u);int o = max(f[v][0], f[v][1] + w[v]);f[u][0] += o;if(f[v][0] + w[v] - o > ma1[u]) son2[u] = son1[u], ma2[u] = ma1[u], ma1[u] = f[v][0] + w[v] - o, son1[u] = v;else if(f[v][0] + w[v] - o > ma2[u]) ma2[u] = f[v][0] + w[v] - o, son2[u] = v;}f[u][1] = f[u][0] + ma1[u];
}
void dfss(int u, int fa) {for(int i = p[u]; i + 1; i = e[i].nxt) {int v = e[i].v, c = e[i].c;if(v == fa) continue;if(son1[u] == v) swap(son1[u], son2[u]), swap(ma1[u], ma2[u]);ls[u][0] = g[u][0] - max(f[v][0], f[v][1] + w[v]);ls[u][1] = ls[u][0] + ma1[u];if(fa) ls[u][1] = max(ls[u][1], ls[u][0] + ls[fa][0] + w[u] - max(ls[fa][0], ls[fa][1] + w[u]));g[v][0] = f[v][0] + max(ls[u][0], ls[u][1] + w[v]);if(ma1[u] < ma2[u]) swap(son1[u], son2[u]), swap(ma1[u], ma2[u]);dfss(v, u);}
}
int main() {init();scanf("%d", &n);for(int i = 1; i < n; i ++) {int u, v, c;scanf("%d%d%d", &u, &v, &c);insert(u, v, c), insert(v, u, c);}dfs(1, 0); g[1][0] = f[1][0];dfss(1, 0);// for(int i = 1; i <= n; i ++) printf("%lld ", f[i][0]); printf("\n");// for(int i = 1; i <= n; i ++) printf("%lld ", g[i][0]); printf("\n");ll ans = 0;for(int i = 1; i <= n; i ++) ans = max(ans, g[i][0]);printf("%lld", ans);return 0;
}

luogu P3647 [APIO2014] 连珠线相关推荐

  1. 洛谷P3647 [APIO2014] 连珠线 题解

    洛谷P3647 [APIO2014] 连珠线 题解 题目链接:P3647 [APIO2014] 连珠线 题意: 在达芬奇时代,有一个流行的儿童游戏称为连珠线.当然,这个游戏是关于珠子和线的.线是红色或 ...

  2. P3647 [APIO2014]连珠线

    题意 传送门 题解 我们发现,如果一棵树的形态固定了,那么蓝线的方向一定是son[x]-x-fa[x],那么我们就可以先随便定一个根进行DP. 我们设f[i][0]f[i][0]f[i][0]表示以i ...

  3. 【BZOJ3677】[Apio2014]连珠线 换根DP

    [BZOJ3677][Apio2014]连珠线 Description 在列奥纳多·达·芬奇时期,有一个流行的童年游戏,叫做"连珠线".不出所料,玩这个游戏只需要珠子和线,珠子从1 ...

  4. [APIO2014]连珠线

    题目链接 分析 首先考虑朴素算法. 可以枚举每个节点作为根,这样的话连接的树的形态就确定了. 应为我们可以知道每个点只可能是一个蓝边的中点,不难想到设一个DP状态表示节点是否为蓝边的中点,设 dp[i ...

  5. APIO2014 连珠线

    题目链接:戳我 换根DP 由于蒟蒻不会做这个题,所以参考了大佬. 本来想的是有三种情况,一种是该节点不作为两个蓝线的中点(我们称这种不是关键节点),一种是该节点作为关键点.连两个子节点,一种是作为关键 ...

  6. [APIO2014]连珠线 题解

    我们设初始的那个点为root.则所有的蓝色链都是形如father−now−sonfather-now-sonfather−now−son. 我们设计两个dp状态: dpi,0dp_{i,0}dpi,0 ...

  7. BZOJ3677: [Apio2014]连珠线

    这题刚了好久的treedp,一直WA比较大的点,不知道哪里错了以为我想法错了看题解结果都说换根好做些不换根很多特殊情况-. 咱觉得咱的想法没问题..,应该是一些细节没考虑好,又想了想一些反例就过去了 ...

  8. [BZOJ3677/UOJ#105][APIO2014]Beads and wires 连珠线(树形dp+换根)

    Address https://www.lydsy.com/JudgeOnline/problem.php?id=3677 http://uoj.ac/problem/105 Solution 考虑一 ...

  9. Luogu P3014 [USACO11FEB]牛线Cow Line

    题目链接:传送门 康托展开模板 不了解的去找资料自学 很好入手 #include <iostream> #include <cstdio> #include <cstri ...

最新文章

  1. SharePoint 2010 技巧系列: 控制Ribbon菜单权限(SiteActions的例子)
  2. python 对象_python面向对象
  3. [POI2008] Poc (原名 Trians) Treap+Hash
  4. 基于贝叶斯决策理论的分类器
  5. boost::metaparse::debug_parsing_error相关用法的测试程序
  6. 《罗辑思维》读书笔记及思维导图
  7. 互联网通用架构技术----缓存雪崩
  8. 多条件and查询遇到的问题
  9. APICloud学习笔记之div样式设置套路
  10. velocity(vm)模板引擎学习介绍及语法
  11. SJCcopula matlab,时变copula的matlab程序
  12. python在线编辑文档-使用python编辑和读取word文档
  13. 团队如何开会,开会准则
  14. 房屋登记官考核模拟题(6)
  15. Convert UOM values
  16. Primer Premierv6.24详细图文安装和破解教程
  17. CSS样式写出三角形
  18. 前端解决web端 125%,150%缩放,1366*768分辨率兼容问题
  19. 当前安装包签名出现异常_关于部分华为手机安装游戏提示“签名异常”问题说明...
  20. 云原生(二十七) | Kubernetes篇之自建高可用k8s集群前置概念与操作

热门文章

  1. 概率论0—概率初步简介
  2. 计算机视觉论文doc,计算机视觉论文.doc
  3. C++ string乱码可能解决方案
  4. 字典树 ZJM 与生日礼物
  5. oracle apex接口文件,Oracle_APEX开发指南
  6. 概率论 —— 随机事件与概率
  7. ubuntu查服务器型号,查看Ubuntu服务器的版本信息
  8. 【2019-09-11】为学日益,为道日损
  9. 包对象之Oracle如何编译失效包体
  10. PMP 考点 第三章 项目经理的角色