• bzoj 4987 Tree —— 树形DP


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4987

    其实就是在树上找有 k 个点的连通块(路径上的点都选是最优的),之间的边都走了两遍,只有一条路径(a[1] -> a[k])走了一遍;

    于是 f[x][j][0/1/2] 表示以 x 为根的子树内选了 k 个点,有 0/1/2 个端点(路径结尾)的最小值;

    但是为什么转移必须是推过去而不能是加回来?TLE...?真是太奇怪了。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int const xn=3005,inf=1e9;
    int n,m,hd[xn],ct,to[xn<<1],nxt[xn<<1],w[xn<<1],f[xn][xn][3],siz[xn],ans;
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;}
    void dfs(int x,int fa)
    {
      siz[x]=1;
      f[x][1][0]=f[x][1][1]=0;
      for(int i=hd[x],u;i;i=nxt[i])
        {
          if((u=to[i])==fa)continue;
          dfs(u,x);
          for(int j=siz[x];j>=1;j--)
              for(int k=siz[u];k>=1;k--)
              {
                f[x][j+k][0]=min(f[x][j+k][0],f[x][j][0]+f[u][k][0]+(w[i]<<1));
                f[x][j+k][1]=min(f[x][j+k][1],min(f[x][j][1]+f[u][k][0]+(w[i]<<1),f[x][j][0]+f[u][k][1]+w[i]));
                f[x][j+k][2]=min(f[x][j+k][2],f[x][j][1]+f[u][k][1]+w[i]);
                f[x][j+k][2]=min(f[x][j+k][2],min(f[x][j][0]+f[u][k][2]+(w[i]<<1),f[x][j][2]+f[u][k][0]+(w[i]<<1)));
              }
    //        for(int j=min(m,siz[x]+siz[u]);j>=2;j--) //--TLE???
    //          for(int k=1;k<=min(j-1,siz[u]);k++)//j-1 
    //          {
    //            f[x][j][0]=min(f[x][j][0],f[x][j-k][0]+f[u][k][0]+(w[i]<<1));
    //            f[x][j][1]=min(f[x][j][1],min(f[x][j-k][1]+f[u][k][0]+(w[i]<<1),f[x][j-k][0]+f[u][k][1]+w[i]));
    //            f[x][j][2]=min(f[x][j][2],f[x][j-k][1]+f[u][k][1]+w[i]);
    //            f[x][j][2]=min(f[x][j][2],min(f[x][j-k][0]+f[u][k][2]+(w[i]<<1),f[x][j-k][2]+f[u][k][0]+(w[i]<<1)));//!
    //          }
          siz[x]+=siz[u];
        }
      for(int i=0;i<=2;i++)ans=min(ans,f[x][m][i]);//
    }
    int main()
    {
      n=rd(); m=rd();
      for(int i=1,x,y,z;i<n;i++)
        {
          x=rd(); y=rd(); z=rd();
          add(x,y,z); add(y,x,z);
        }
      memset(f,0x3f,sizeof f); ans=inf;
      dfs(1,0);
      printf("%d
    ",ans);
      return 0;
    }
  • 相关阅读:
    男人应该懂得的
    喝酒礼仪
    Office Web Apps开放测试
    SAP系统概要
    SAP实施成功的关键因素
    SAP企业实施的方法论
    ASAP
    ERP系统的组成部分
    去除word的保护
    实习周小结
  • 原文地址:https://www.cnblogs.com/Zinn/p/9821326.html
Copyright © 2020-2023  润新知