[poj 1947] Rebuilding Roads 트리 DP

5106 단어 poj트리 DP
Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 10653 Accepted: 4884
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
    제목 링크:http://poj.org/problem?id=1947
    제목: n의 나무 한 그루를 주고 최소한 몇 칼은 베어도 m의 나무 한 그루를 고립시킬 수 있는지 물어본다.
    사고방식: 뿌리 노드(입도 0)를 찾은 후 dfs는 각 노드에서 dp[i][j]를 통계하여 i와 그의 하위 트리가 j개 노드를 보존하는 최소 대가를 나타낸다.
    int tmp=dp[x][ii]+1;//  y  ;
    tmp=min(tmp,dp[x][ii-j]+dp[y][j]);
    dp[x][ii]=tmp;

    y는 x의 아들 노드이다.
    코드:
    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<vector>
    using namespace std;
    
    int dp[155][155];
    int ans;
    int in[155];
    vector<int> lin[155];
    int n,aa,bb,p;
    void dfs(int x)
    {
        for(int i=2;i<=p;i++) dp[x][i]=99999999;
        if(lin[x].size()==0)
        dp[x][1]=0;
        for(int i=0;i<lin[x].size();i++)
        {
            int y=lin[x][i];
            dfs(y);
            for(int ii=p;ii>=1;ii--)
            {
                int tmp=dp[x][ii]+1;
                for(int j=1;j<ii;j++)
                tmp=min(tmp,dp[x][ii-j]+dp[y][j]);
                dp[x][ii]=tmp;
            }       
        }
    }
    int main()
    {
        scanf("%d%d",&n,&p);
        {
            int ans=99999999;
            for(int i=1;i<n;i++)
            {
                scanf("%d%d",&aa,&bb);
                lin[aa].push_back(bb);
                in[bb]++;
            }
            for(int i=1;i<=n;i++)
            if(!in[i])
            {
                dfs(i);
                ans=dp[i][p];
                break;
            }
    
            for(int i=1;i<=n;i++)
            ans=min(ans,dp[i][p]+1);
            printf("%d
    "
    ,ans); } }

    좋은 웹페이지 즐겨찾기