zoukankan      html  css  js  c++  java
  • 重建道路 (树上背包问题)

    重建道路

    题目链接

    This is -single$hot

    题目

    一场可怕的地震后,人们用 N 个牲口棚(编号 1∼N)重建了农夫 John 的牧场。由于人们没有时间建设多余的道路,所以现在从一个牲口棚到另一个牲口棚的道路是惟一的。因此,牧场运输系统可以被构建成一棵树。

    John 想要知道另一次地震会造成多严重的破坏。有些道路一旦被毁坏,就会使一棵含有 P 个牲口棚的子树和剩余的牲口棚分离,John 想知道这些道路的最小数目。

    分析

    这是一个典型的树上背包问题
    类似一个多重背包,这个一般是树形DP的难题。

    题解已经很清晰了,下面是代码 :

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 310;
    inline int read(int s = 0, int f = 1, char ch = getchar()) {
        while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); }
        while(isdigit(ch)) { s = s*10 + ch - '0'; ch = getchar(); }
        return s * f;
    }
    int n, p, chu[N], in[N], f[N][N], head[N], cnt, root, ans;
    struct edge { int to, next; } e[N<<1];
    inline void add(int x, int y) { e[++cnt].to = y, e[cnt].next = head[x], head[x] = cnt; }
    int dfs(int u) {
        int temp, sum = 1;
        for(int i = head[u], v; i; i = e[i].next) {
        	v = e[i].to, temp = dfs(v), sum += temp;
        	for(int j = sum; j >= 1; j--) 
        		for(int k = 1; k < j; ++k)
        			f[u][j] = min(f[u][j], f[u][j - k] + f[v][k] - 1);
        }
        return sum;
    }
    int main() {
        n = read(), p = read();
        for(int i = 1, x, y; i <= n-1; ++i) 
        	x = read(), y = read(), chu[x]++, in[y]++, add(x, y);
        memset(f, 0x3f, sizeof(f));
        for(int i = 1; i <= n; ++i) {
        	if(in[i] == 0) root = i;
        	f[i][1] = chu[i];
        }
        dfs(root);
        ans = f[root][p];
        for(int i = 1; i <= n; ++i)  ans = min(ans, f[i][p] + 1);
        return cout << ans, 0;
    }
    
    
  • 相关阅读:
    java序列化进阶
    jQuery学习一(选择器)
    java poi 操作Excel常用方法总结
    mybatis批量foreach的使用
    java中关于try、catch、finally的总结
    MyEclipse使用指南(精简版)
    单例模式
    抽象工厂模式
    java.io.Serializable
    java.lang.string
  • 原文地址:https://www.cnblogs.com/DZN2004/p/13420343.html
Copyright © 2011-2022 走看看