zoukankan      html  css  js  c++  java
  • 重建道路

    传送门

    我们来看一道比较可做的树形DP。

    现在这个数据规模的树形DP都是可以直接n3暴力转移过掉的呀……

    不过这个状态比较特殊,我们用dp[i][j]表示i节点在子树中保留j个节点所需要删去的最小边数。

    那么转移方程就是,dp[i][j] = min(dp[i][j],dp[i][j-k] + dp[v][k] - 1);其中那个-1是节点i和节点v之间的连边,那个是要保留的orz,他之前会被重复计算。

    所以我们直接这样暴力dp即可,一开始的初始化是dp[i][1] = son[i],son表示子节点个数。

    看一下代码。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 10005;
    const int INF = 1000000009;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            ans *= 10;
            ans += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    
    struct edge
    {
        int next,to,v;
    }e[10005];
    
    int son[10005],n,p,dp[3005][3005],x,y,ecnt,head[10005],sum[10005];
    
    void add(int x,int y)
    {
        e[++ecnt].to = y;
        e[ecnt].next = head[x];
        head[x] = ecnt;
    }
    
    void dfs(int x,int fa)
    {
        sum[x] = 1;
        bool flag = 1;
        for(int i = head[x];i;i = e[i].next)
        {
            int k = e[i].to;
            if(k == fa) continue;
            flag = 0;
            dfs(k,x);
            sum[x] += sum[k];
            per(j,sum[x],0)
            rep(p,1,j-1) dp[x][j] = min(dp[x][j],dp[x][j-p] + dp[k][p] - 1);
        }
        if(flag)
        {
            dp[x][1] = 0;
            sum[x] = 1;
            return;
        }
    }
    
    int main()
    {
        n = read(),p = read();
        rep(i,1,n-1) x = read(),y = read(),add(x,y),add(y,x),son[x]++;
        memset(dp,127/3,sizeof(dp));
        rep(i,1,n) dp[i][1] = son[i];
        dfs(1,0);
        int ans = dp[1][p];
        rep(i,2,n) ans = min(ans,dp[i][p] + 1);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Python 数据处理 正则匹配,清洗脏数据
    Pycharm自用激活码
    编程杂谈 集群与分布式
    win10 向右键添加管理员级CMD
    win10 笔记本键盘永久屏蔽Numlk键
    Golong 环境搭建
    python 各种锁机制归纳整理
    MySQL数据库操作
    Web框架本质
    Django框架
  • 原文地址:https://www.cnblogs.com/captain1/p/9649610.html
Copyright © 2011-2022 走看看