zoukankan      html  css  js  c++  java
  • [IOI2005] Riv 河流

    18.10.03模拟赛T3。

    xcj丧心病狂出了道IOI的题???(虽然是2005年的)

    而且被zwz当场切掉???(这个已经习惯了)

    洛谷 P3354 传送门

    bzoj1812 传送门

    树形DP。

    本来以为是二维的:f[p][k]表示p的子树里放k个得到的最小值。

    然后就没搞出来。

    正解是三维的:f[p][fa][k]表示p的子树里放k个,p的祖先节点里的最近的在fa,得到的最小值。

    转移之前需要先求出点之间的距离。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 int n,k;
     7 int fa[105],v[105];
     8 int dis[105][105];
     9 int f[105][105][55];
    10 int hd[105],nx[105],to[105],ec;
    11 
    12 void edge(int af,int at)
    13 {
    14     to[++ec]=at;
    15     nx[ec]=hd[af];
    16     hd[af]=ec;
    17 }
    18 
    19 void dfs(int p)
    20 {
    21     int s=p;
    22     for(int i=fa[p];i!=-1;i=fa[i])
    23     {
    24         dis[p][i]=dis[p][s]+dis[s][i];
    25         s=i;
    26     }
    27     if(!hd[p])
    28     {
    29         for(int i=fa[p];i!=-1;i=fa[i])
    30             f[p][i][0]=dis[p][i]*v[p];
    31         return;
    32     }
    33     if(p)f[p][p][0]=0x3f3f3f3f;
    34     for(int i=hd[p];i;i=nx[i])
    35     {
    36         int t=to[i];
    37         dfs(t);
    38         for(int ff=fa[p];ff!=-1;ff=fa[ff])
    39         {
    40             for(int j=k;j>=0;j--)
    41             {
    42                 int tv=0x3f3f3f3f;
    43                 for(int l=0;l<=j;l++)
    44                 {
    45                     tv=min(tv,f[p][ff][l]+f[t][ff][j-l]);
    46                 }
    47                 f[p][ff][j]=tv;
    48             }
    49         }
    50         for(int j=k;j>=0;j--)
    51         {
    52             int tv=0x3f3f3f3f;
    53             for(int l=(p!=0);l<=j;l++)
    54             {
    55                 tv=min(tv,f[p][p][l]+f[t][p][j-l]);
    56             }
    57             f[p][p][j]=tv;
    58         }
    59     }
    60     for(int i=fa[p];i!=-1;i=fa[i])
    61     {
    62         for(int j=0;j<=k;j++)
    63         {
    64             f[p][i][j]+=dis[p][i]*v[p];
    65             f[p][i][j]=min(f[p][i][j],f[p][p][j]);
    66         }
    67     }
    68 }
    69 
    70 int main()
    71 {
    72     scanf("%d%d",&n,&k);
    73     for(int i=1;i<=n;i++)
    74     {
    75         int w;
    76         scanf("%d%d%d",&v[i],&fa[i],&w);
    77         dis[i][fa[i]]=w;
    78         edge(fa[i],i);
    79     }
    80     fa[0]=-1;
    81     dfs(0);
    82     printf("%d
    ",f[0][0][k]);
    83     return 0;
    84 }
  • 相关阅读:
    Android 数据库框架 DBFlow 的使用
    Android进阶AIDL使用自定义类型
    Android进阶之AIDL的使用详解
    RecyclerView实现拖动排序和滑动删除功能
    RecyclerView的刷新分页
    RecyclerView 的 Item 的单击事件
    RecyclerView 的简单使用
    AutoCompleteTextView的简单使用
    Spinner的简单实用
    黎曼猜想
  • 原文地址:https://www.cnblogs.com/eternhope/p/9741761.html
Copyright © 2011-2022 走看看