zoukankan      html  css  js  c++  java
  • hdu6769 In Search of Gold

    题目描述:

    给定一个颗树,每一条边有俩个权值w1和w2。选择k条边权为w1的边,其余都是w2。让直径最小。

    题解:

    树形dp,f[u][k]表示以u为根结点的子树的最小直径,因为直接求不好求,可以二分判可行性,求出答案。考虑转移,类似背包。

     if(f[u][k] + f[j][z] + A <= mid) tmp[k + z + 1] = min(tmp[k + z + 1], max(f[u][k], f[j][z] + A));

     if(f[u][k] + f[j][z] + B <= mid) tmp[k + z] = min(tmp[k + z], max(f[u][k], f[j][z] + B));

     

     

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int N = 2e4 + 10;
     5 const int M = 4e4 + 10;
     6 typedef long long ll;
     7 inline int read()
     8 {
     9     char ch = getchar();int x = 0, f = 1;
    10     while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    11     while(ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) - '0' + ch; ch = getchar();}
    12     return x * f;
    13 }
    14 
    15 ll f[N][21];
    16 ll tmp[21];
    17 int n, m, t;
    18 int size[N];
    19 int h[N], e[M], ne[M], idx, w1[M], w2[M];
    20 
    21 
    22 void init()
    23 {
    24     idx = 0;
    25     for (int i = 1; i <= n; i ++) h[i] = -1;
    26 }
    27 
    28 void add(int a, int b, int c, int d)
    29 {
    30     w1[idx] = c;
    31     w2[idx] = d;
    32     e[idx] = b;
    33     ne[idx] = h[a];
    34     h[a] = idx ++;
    35 }
    36 
    37 void dfs(int u, int fa, ll mid)
    38 {
    39     size[u] = f[u][0] = 0;
    40     for (int i = h[u]; ~i; i = ne[i])
    41     {
    42         int j = e[i];
    43         if(j == fa) continue;
    44         dfs(j, u, mid);
    45         ll A = w1[i], B = w2[i];
    46        // size[u] += size[j];
    47         int pre = size[u], cur = size[j];
    48         int now = min(pre + cur + 1, m);
    49         for (int k = 0; k <= now; k ++)
    50             tmp[k] = mid + 1;
    51         for (int k = 0; k <= pre; k ++)
    52         {
    53             for (int z = 0; z + k <= now && z <= cur; z ++)
    54             {
    55                 if(f[u][k] + f[j][z] + A <= mid) tmp[k + z + 1] = min(tmp[k + z + 1], max(f[u][k], f[j][z] + A));
    56                 if(f[u][k] + f[j][z] + B <= mid) tmp[k + z] = min(tmp[k + z], max(f[u][k], f[j][z] + B));
    57             }
    58         }
    59         size[u] = now;
    60         for (int j = 0; j <= now; j ++) f[u][j] = tmp[j];
    61     }
    62 }
    63 
    64 int main()
    65 {
    66     t = read();
    67     while(t --)
    68     {
    69         n = read(), m = read();
    70         init();
    71         ll l = 0, r = 0;
    72         for (int i = 1; i <= n - 1; i ++)
    73         {
    74             int a = read(), b = read(), x = read(), y = read();
    75             add(a, b, x, y); add(b, a, x, y);
    76             r += max(x, y);
    77         }
    78         while(l < r)
    79         {
    80             ll mid = l + r >> 1;
    81             dfs(1, 0, mid);
    82             if(f[1][m] <= mid) r = mid;
    83             else l = mid + 1;
    84         }
    85         printf("%lld
    ", r);
    86     }
    87 }
    View Code
  • 相关阅读:
    结对编程项目---四则运算
    作业三(代码规范、代码复审、PSP)
    作业2(源程序管理软件与项目管理软件)
    学习总结
    作业1
    寒假超市实习
    《软件工程》课程总结
    结对编程项目---四则运算
    作业三: 代码规范、代码复审、PSP
    作业二(2)目前流行的源程序版本管理软件和项目管理软件都有哪些,各有什么优缺点?
  • 原文地址:https://www.cnblogs.com/xwdzuishuai/p/14083696.html
Copyright © 2011-2022 走看看