Rebuilding-Roads-POJ-1947

Rebuilding Roads POJ - 1947

Last Edited: May 27, 2019 7:32 PM
Tags: dynamic programming,poj

設定dp[u][j]爲以u爲根大小爲j的最小值

  1. 注意dp[u][1] 爲1
  2. 對於每個節點若考慮去除某個子節點顯然其已知的dp[u][j]應加一
  3. 對於保留某子節點的情況需考慮當前爲j的情況以及其子節點取k個的情況易得遞推式dp[u][j]=dp[u][j-k]+dp[v][k],所以可以得到其必然有子節點至少取一個(不取情況爲見2)
#include<cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define fst first
#define sec second
#define sci(num) scanf("%d",&num)
#define scl(num) scanf("%lld",&num)
#define mem(a,b) memset(a,b,sizeof a)
#define cpy(a,b) memcopy(a,b,sizeof b)
#define lc (rt<<1)
#define rc (rt<<1|1)
typedef long long LL;
typedef pair<int,int> P;
const int MAX_N = 200;
const int MOD = 1e9 + 7;
int N,M;
int dp[MAX_N][MAX_N];
vector<int> G[MAX_N];
int fa[MAX_N];
void dfs(int u) {
    dp[u][1] = 0;
    for (int i = 0;i < G[u].size();i++) {
        int v =  G[u][i];
        dfs(v);
        for (int j = M;j >= 1;j--) {
            dp[u][j]++;
            for (int k = 1;k < j;k++) {
                dp[u][j] = min(dp[u][j],dp[v][k]+dp[u][j - k]);
            }
        }
    }
}
int main() {
    while (~scanf("%d%d",&N,&M)) {
        mem(fa,-1);
        mem(dp,0x3f3f3f3f);
        for (int i = 0;i <= N;i++)
            G[i].clear();
        for (int i = 1;i < N;i++) {
            int u,v;
            sci(u); sci(v);
            G[u].push_back(v);
            fa[v] = u;
        }
        int ans;
        for (int i = 1;i <= N;i++) {
            if (fa[i] != -1) continue;
            dfs(i);
            ans = dp[i][M];
            break;
        }
        for (int i = 1;i <= N;i++) {
            ans = min(ans,dp[i][M]+1);
        }
        printf("%d\n",ans);
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章