[关闭]
@y20070316 2017-04-22T13:06:19.000000Z 字数 1862 阅读 961

XSY 2176 - tree

题目精选 树形dp 序的应用


题意

分析

  给定 个点 ,定义 ,它的树链的并的值就是


  回到本题,我们所求就是 的最小值。

  我们考虑进行树形dp。
:在以 为根的子树中,选了 个点,子树内有 条出现次数为 的路径 的最小值。
:在以 为根的子树中,选了 个点,子树内有 条出现次数为 的路径,且路径的终点为根 的最小值。
:在以 为根的子树中,选了 个点,子树内有 条出现次数为 的路径 的最小值。

  dp的方法很容易,这里不赘述。

实现

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cctype>
  4. #include <algorithm>
  5. using namespace std;
  6. #define F(i,a,b) for (register int i=(a);i<=(b);i++)
  7. #define D(i,a,b) for (register int i=(a);i>=(b);i--)
  8. const int N=3005;
  9. const int E=6005;
  10. const int INF=~0u>>2;
  11. int n,nk;
  12. struct Ed {
  13. int v,d,nx;
  14. inline Ed(int _v=0,int _d=0,int _nx=0):v(_v),d(_d),nx(_nx){}
  15. }mp[E];
  16. int tot,hd[N];
  17. int siz[N];
  18. int f[N*N];
  19. int g[N*N];
  20. int h[N*N];
  21. int ans;
  22. inline int rd(void) {
  23. int x=0,f=1; char c=getchar();
  24. for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
  25. for (;isdigit(c);c=getchar()) x=x*10+c-'0';
  26. return x*f;
  27. }
  28. inline void Ins(int u,int v,int d) {
  29. mp[++tot]=Ed(v,d,hd[u]); hd[u]=tot;
  30. mp[++tot]=Ed(u,d,hd[v]); hd[v]=tot;
  31. }
  32. inline void gmin(int &x,int y) {
  33. x=min(x,y);
  34. }
  35. inline int id(int i,int j) {
  36. return (i-1)*n+j;
  37. }
  38. void DP(int x,int pre) {
  39. int t=1;
  40. for (int k=hd[x];k>0;k=mp[k].nx)
  41. if (mp[k].v!=pre) {
  42. DP(mp[k].v,x);
  43. t+=siz[mp[k].v];
  44. }
  45. siz[x]=1;
  46. f[id(x,1)]=g[id(x,1)]=h[id(x,1)]=0;
  47. F(i,2,t) f[id(x,i)]=g[id(x,i)]=h[id(x,i)]=INF;
  48. for (int k=hd[x];k>0;k=mp[k].nx)
  49. if (mp[k].v!=pre) {
  50. int son=mp[k].v,d=mp[k].d;
  51. D(i,siz[x],1) F(j,1,siz[son]) {
  52. gmin(f[id(x,i+j)],f[id(x,i)]+f[id(son,j)]+2*d);
  53. gmin(g[id(x,i+j)],g[id(x,i)]+f[id(son,j)]+2*d);
  54. gmin(g[id(x,i+j)],f[id(x,i)]+g[id(son,j)]+d);
  55. gmin(h[id(x,i+j)],h[id(x,i)]+f[id(son,j)]+2*d);
  56. gmin(h[id(x,i+j)],g[id(x,i)]+g[id(son,j)]+d);
  57. gmin(h[id(x,i+j)],f[id(x,i)]+h[id(son,j)]+2*d);
  58. }
  59. siz[x]+=siz[son];
  60. }
  61. }
  62. int main(void) {
  63. #ifndef ONLINE_JUDGE
  64. freopen("sdchr.in","r",stdin);
  65. freopen("sdchr.out","w",stdout);
  66. #endif
  67. cin>>n>>nk;
  68. F(i,1,n-1) {
  69. int x=rd(),y=rd(),d=rd();
  70. Ins(x,y,d);
  71. }
  72. DP(1,-1);
  73. ans=INF; F(i,1,n) if (siz[i]>=nk) gmin(ans,h[id(i,nk)]); cout<<ans<<endl;
  74. return 0;
  75. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注