Written with StackEdit.

Description

从前有棵树。

找出\(K\)个点\(A_1,A_2,…,A_K\)。

使得\(∑dis(A_i,A_{i+1}),(1<=i<=K-1)\)最小。

Input

第一行两个正整数\(n,k\),表示数的顶点数和需要选出的点个数。

接下来\(n-1\)行每行3个非负整数\(x,y,z\),表示从存在一条从\(x\)到\(y\)权值为\(z\)的边。

\(1<=k<=n\)

\(1<x,y<=n\)

\(1<=z<=10^5\)

\(n <= 3000\)

Output

一行一个整数,表示最小的距离和。

Sample Input

10 7

1 2 35129

2 3 42976

3 4 24497

2 5 83165

1 6 4748

5 7 38311

4 8 70052

3 9 3561

8 10 80238

Sample Output

184524

Solution

  • 注意到选择的点集一定是两两相邻的.
  • 那么选出的点中,只有一条链可以只经过一次,其余的需要经过两次.
  • 考虑树形背包选边,令\(f(i,j,k)\)表示在子树\(i\)中选出\(j\)条边的最小代价,
    • \(k=0\):回到根节点.
    • \(k=1\):不回到根节点.
    • \(k=2\):回到根节点后再下去.
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LoveLive;
  4. inline int read()
  5. {
  6. int out=0,fh=1;
  7. char jp=getchar();
  8. while ((jp>'9'||jp<'0')&&jp!='-')
  9. jp=getchar();
  10. if (jp=='-')
  11. {
  12. fh=-1;
  13. jp=getchar();
  14. }
  15. while (jp>='0'&&jp<='9')
  16. {
  17. out=out*10+jp-'0';
  18. jp=getchar();
  19. }
  20. return out*fh;
  21. }
  22. const int MAXN=3e3+10;
  23. int cnt=0,head[MAXN];
  24. int nx[MAXN<<1],to[MAXN<<1],val[MAXN<<1];
  25. inline void add(int u,int v,int w)
  26. {
  27. ++cnt;
  28. nx[cnt]=head[u];
  29. to[cnt]=v;
  30. val[cnt]=w;
  31. head[u]=cnt;
  32. }
  33. int f[MAXN][MAXN][3],siz[MAXN];
  34. inline void upd(int &x,int y)
  35. {
  36. if(x>y)
  37. x=y;
  38. }
  39. void dfs(int u,int fa)
  40. {
  41. siz[u]=1;
  42. f[u][0][0]=f[u][0][1]=0;
  43. for(int i=head[u];i;i=nx[i])
  44. {
  45. int v=to[i];
  46. if(v==fa)
  47. continue;
  48. dfs(v,u);
  49. for(int j=siz[u]-1;j>=0;--j)
  50. for(int k=siz[v]-1;k>=0;--k)
  51. for(int l=2;l>=0;--l)
  52. for(int m=l;m>=0;--m)
  53. upd(f[u][j+k+1][l],f[u][j][l-m]+f[v][k][m]+val[i]*(2-(m & 1)));
  54. siz[u]+=siz[v];
  55. }
  56. }
  57. int n,m;
  58. int main()
  59. {
  60. n=read(),m=read();
  61. for(int i=1;i<n;++i)
  62. {
  63. int u=read(),v=read(),w=read();
  64. add(u,v,w);
  65. add(v,u,w);
  66. }
  67. memset(f,0x3f,sizeof f);
  68. dfs(1,0);
  69. int ans=0x7fffffff;
  70. for(int i=1;i<=n;++i)
  71. for(int j=0;j<=2;++j)
  72. ans=min(ans,f[i][m-1][j]);
  73. printf("%d\n",ans);
  74. return 0;
  75. }

参考了dalao的blog.

bzoj 4987 Tree的更多相关文章

  1. bzoj 4987 Tree —— 树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4987 其实就是在树上找有 k 个点的连通块(路径上的点都选是最优的),之间的边都走了两遍,只 ...

  2. bzoj 2212 Tree Rotations

    bzoj 2212 Tree Rotations 考虑一个子树 \(x\) 的左右儿子分别为 \(ls,rs\) .那么子树 \(x\) 内的逆序对数就是 \(ls\) 内的逆序对数,\(rs\) 内 ...

  3. bzoj 2631: tree 动态树+常数优化

    2631: tree Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1716  Solved: 576[Submit][Status] Descrip ...

  4. [BZOJ - 2631] tree 【LCT】

    题目链接:BZOJ - 2631 题目分析 LCT,像线段树区间乘,区间加那样打标记. 这道题我调了一下午. 提交之后TLE了,我一直以为是写错了导致了死循环. 于是一直在排查错误.直到.. 直到我看 ...

  5. [BZOJ 3282] Tree 【LCT】

    题目链接:BZOJ - 3282 题目分析 这道题是裸的LCT,包含 Link , Cut 和询问两点之间的路径信息. 写代码时出现的错误:Access(x) 的循环中应该切断的是原来的 Son[x] ...

  6. BZOJ 2654: tree( 二分 + MST )

    我们给白色的边增加权值 , 则选到的白色边就会变多 , 因此可以二分一下. 不过这道题有点小坑... ------------------------------------------------- ...

  7. BZOJ 3282: Tree( LCT )

    LCT.. -------------------------------------------------------------------------------- #include<c ...

  8. BZOJ 2631: tree( LCT )

    LCT...略麻烦... -------------------------------------------------------------------------------- #inclu ...

  9. BZOJ 3282 Tree Link-Cut-Tree(LCT)

    题目大意: 给定N个点以及每一个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y ...

随机推荐

  1. 使用GoogleCode作SVN服务器的一些问题及解决办法

    1.首先最主要的一个问题,就是注册GoogleCode和安装SVN工具. 网上教程很多,不一一赘述.http://www.th7.cn/Program/net/201305/136059.shtml ...

  2. 【c++习题】【17/4/16】动态分配内存

    #include<iostream> #include<cstring> #define N 100 using namespace std; class String{ pu ...

  3. Forward Proxy vs Reverse Proxy

    Overview We've talked about reverse proxy servers and how they can really be good at protecting the ...

  4. 20145219 《Java程序设计》第07周学习总结

    20145219 <Java程序设计>第07周学习总结 教材学习内容总结 认识时间与日期 时间的度量 1.格林威治时间(GMT):通过观察太阳而得,因为地球公转轨道为椭圆形且速度不一,本身 ...

  5. Block作为返回值时的使用

    昨天使用一个小例子简单说明了下Block作为参数时的使用. 今天再来复习一下Block作为返回值使用时的情况,先贴一小段热门第三方框架Masonry的官方sample code: [view1 mas ...

  6. Facebook力推导航库:React Navigation使用详解

    本文来自Songlcy投稿:文章地址:http://blog.csdn.net/u013718120/article/details/72357698 一.开源库介绍 今年1月份,新开源的react- ...

  7. SMM+maven下的log4j配置打印sql

    1加入依赖包 <!--LOG4日志 start --> <dependency> <groupId>org.slf4j</groupId> <ar ...

  8. bootstrap正则表达式验证手机 座机 邮箱

    $('#CusForm').bootstrapValidator({ fields : { //验证手机 'customer.mobile' : { //input中的name 值 validator ...

  9. JAVA实现计算三角形等平面图形的夹角问题

    问题重现 现在一平面上有三点,分别是x(x1,x2),y(y1,y2),z(z1,z2),图形大致如下 现要求用java代码求出∠YxZ的度数. 问题分析及数学模型 1.要求两直线的夹角,就想到数学中 ...

  10. thrift安装及常见问题

    一.安装thrift (macOS / Linux) 1. 下载thrift0.10.0源码 https://github.com/apache/thrift/releases/tag/0.10.0 ...