zoukankan      html  css  js  c++  java
  • poj 1947(树形DP+背包)

    Rebuilding Roads
    Time Limit: 1000MS   Memory Limit: 30000K
    Total Submissions: 10663   Accepted: 4891

    Description

    The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The cows didn't have time to rebuild any extra roads, so now there is exactly one way to get from any given barn to any other barn. Thus, the farm transportation system can be represented as a tree.

    Farmer John wants to know how much damage another earthquake could do. He wants to know the minimum number of roads whose destruction would isolate a subtree of exactly P (1 <= P <= N) barns from the rest of the barns.

    Input

    * Line 1: Two integers, N and P

    * Lines 2..N: N-1 lines, each with two integers I and J. Node I is node J's parent in the tree of roads.

    Output

    A single line containing the integer that is the minimum number of roads that need to be destroyed for a subtree of P nodes to be isolated.

    Sample Input

    11 6
    1 2
    1 3
    1 4
    1 5
    2 6
    2 7
    2 8
    4 9
    4 10
    4 11
    

    Sample Output

    2

    Hint

    [A subtree with nodes (1, 2, 3, 6, 7, 8) will become isolated if roads 1-4 and 1-5 are destroyed.]

    题意:在n个结点n-1条边的树中取m个点所需要的最少切割数.

    分析:dp[u][i]代表以u为根节点的子树要得到i个结点的子树需要最少的切割数 如果考虑u的子树v,如果我们在除去v之外的父亲树中取k个点,那么在子树中取i-k个点
    dp[u][i] = min(dp[u][k]+dp[v][i-k]) ........1
    如果不考虑v,那么我们只需要一刀将子树k与父亲分开即可dp[u][i] = dp[u][i]+1; ..........2
    综上述:dp[u][i] = min(1,2)
    我们在考虑u的时候,等于u是一个容量为m(m为背包容量)的背包,在子树中取m个结点组成,每个点只有取或不取一个,所以可以将其看成01背包。

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <algorithm>
    #define N 155
    using namespace std;
    
    int head[N];
    struct Edge{
        int u,v,next;
    }edge[N];
    
    int indegree[N];
    void addEdge(int u,int v,int &k){
        edge[k].u = u,edge[k].v = v;
        edge[k].next = head[u],head[u]=k++;
    }
    int n,m;
    int dp[N][N];///dp[u][i]代表以u为根节点的子树要得到i个结点的子树需要最少的切割数
    /// 如果考虑u的子树v,如果我们在父亲树中取k个点,那么在子树中取i-k个点
    ///dp[u][i] = min(dp[u][k],dp[v][i-k])
    ///如果不考虑v,那么我们只需要一刀将子树k与父亲分开即可 dp[u][i] = dp[u][i]+1;
    ///综上述:dp[u][i] = min(min(dp[u][k],dp[v][i-k]),dp[u][i]+1)
    ///我们在考虑u的时候,等于u是一个容量为m(m为背包容量)的背包,在子树中取m个结点组成,每个点只有取或不取且最多取一次,所以
    void dfs(int u){
        for(int i=0;i<=m;i++) dp[u][i]=999999;
        dp[u][1]=0; ///初始化只取自己一个点
        for(int k = head[u];k!=-1;k=edge[k].next){
            int v = edge[k].v;
            dfs(v);
            for(int j=m;j>=1;j--){ ///逆序枚举
                dp[u][j]+=1; ///不取子树时
                for(int k=1;k<j;k++){ ///父亲树上取得点
                    int t = j-k; ///子树上取的点
                    dp[u][j] = min(dp[u][k]+dp[v][t],dp[u][j]);
                }
            }
        }
    }
    int main()
    {
    
        while(scanf("%d%d",&n,&m)!=EOF){
            memset(indegree,0,sizeof(indegree));
            memset(head,-1,sizeof(head));
            int tot = 0;
            int u,v;
            for(int i=1;i<n;i++){
                scanf("%d%d",&u,&v);
                addEdge(u,v,tot);
                indegree[v]++;
            }
            int root ;
            for(int i=1;i<=n;i++) if(indegree[i]==0){root = i;break;}
            //printf("%d
    ",root);
            dfs(root);
            int ans = dp[root][m];
            for(int i=1;i<=n;i++){ ///加一是因为父亲结点和它之间还有边连着
                if(dp[i][m]+1<ans) ans = dp[i][m]+1;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    java url 获取文件_[转]从URL获取文件保存到本地的JAVA代码,url 请求设置http请求头
    解决Mybatis中出现的Invalid bound statement (not found)问题
    使用多线程往LIST添加数据 线程安全list
    spring BeanUtils 工具实现对象之间的copy 属性复制,属性拷贝
    idea 打开Service窗口一个管理所有服务的地方
    java实现大文件下载(http方式)
    Java @Override注解写与不写的区别
    Linux下C++共享内存
    Linux配置开机自启
    Linux中zsh出现 zsh: corrupt history file /XXX/.zsh_history解决办法
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5418016.html
Copyright © 2011-2022 走看看