zoukankan      html  css  js  c++  java
  • POJ 1947 Rebuilding Roads


    树形DP。。。。。
    Rebuilding Roads
    Time Limit: 1000MSMemory Limit: 30000K
    Total Submissions: 8188Accepted: 3659

    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.] 

    Source

    USACO 2002 February 

    现在设dp[j]表示以i为根的子树中节点个数为j的最少删除边数

    状态转移方程: dp[1] = tot                                         (tot为他的子节点个数)

                          dp[j] = min(dp[j],dp[k]-1+dp[s][j-k])  (1<=i<=n,2<=j<=sum(节点总和),1<=k<j,s为i子节点)(i中已有k个节点并从s中选择j-k个,算最少删除边数,s选上所以i->s的边不需删除,所以-1)


    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>

    using namespace std;

    const int INF=0x3f3f3f3f;

    int dp[200][200],sum[200],N,P;
    vector<int> g[200];
    bool vis[200];

    void Tree_DP(int s)
    {
        if(vis[s]) return;
        int tot = 0;
        vis[s]=true;sum[s]=1;
        for(int i=0;i<g[s].size();i++)
        {
            int v=g[s];
            if(vis[v]) continue;
            Tree_DP(v);
            sum[s]+=sum[v];
            tot++;
        }
        dp[s][1]=tot;
        for(int i=0;i<g[s].size();i++)
        {
            int v=g[s];
            for(int j=sum[s];j>=2;j--)
            {
                for(int k=1;k<j;k++)
                {
                    if(dp[s][k]!=INF&&dp[v][j-k]!=INF)
                    {
                        dp[s][j]=min(dp[s][j],dp[s][k]+dp[v][j-k]-1);
                    }
                }
            }
        }
    }

    int main()
    {
        while(scanf("%d%d",&N,&P)!=EOF)
        {
            for(int i=0;i<N+10;i++)
                g.clear();
            for(int i=0;i<N-1;i++)
            {
                int a,b;
                scanf("%d%d",&a,&b);
                g[a].push_back(b);
                g.push_back(a);
            }
            memset(dp,63,sizeof(dp));
            memset(vis,false,sizeof(vis));
            memset(sum,0,sizeof(sum));
            Tree_DP(1);
            int ans=INF;
            for(int i=1;i<=N;i++)
            {
                if(i==1)
                    ans=min(ans,dp[P]);
                else ans=min(dp[P]+1,ans);
            }
            printf("%d ",ans);
        }
        return 0;
    }
    * This source code was highlighted by YcdoiT. ( style: Codeblocks )
  • 相关阅读:
    什么是反向代理,反向代理有什么好处?
    动态的favicons
    管理emacs dotemacs文件
    自己的部分小软件合计 2000 2013(很久没有更新了)
    经典CSS 横向导航菜单【下载】
    Web 调试,兼容浏览器的在线调试(系列)
    sql server 执行大脚本时报警告没有足够的内存继续执行程序
    c#对接顺丰图片文件
    Sql Server行转列 动态拼接sql
    centos6.2更新yum源
  • 原文地址:https://www.cnblogs.com/CKboss/p/3350821.html
Copyright © 2011-2022 走看看