• 思维+树形dp——gym101677A (难)


    /*
    拼接思想:
        g[u][j]表示u子树里距离u距离>=j的所有点都被覆盖的代价(子树里扣掉一个以u为圆心的扇形) 
            g[u][j]=sum{g[v][j-1]} 
        f[u][j]表示u子树内以及距离u距离<=j的所有点都被覆盖的代价 (子树加上以u为圆心的圆) 
            f[u][j]=min(f[v][j+1]-g[v][j],j)+g[u][j+1] 
        这两个数组不能独立求,因为g[u][0]是由f[u][0]决定 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define N 5005
    
    vector<int>G[N];
    int n,f[N][N],g[N][N],d[N];
    
    void dfs(int u,int pre){
        for(auto v:G[u])
            if(v!=pre)dfs(v,u);
        for(int i=1;i<=n;i++)
            for(auto v:G[u]){
                if(v==pre)continue;
                g[u][i]+=g[v][i-1];
            }
        f[u][n]=n;//给f[u]顶一个初始状态 
        for(int i=n-1;i>=0;i--){
            f[u][i]=max(1,i)+g[u][max(1,i)+1];//在u处放基站的代价 
            f[u][i]=min(f[u][i],f[u][i+1]);//和之前的比较 
            for(auto v:G[u]){
                if(v==pre)continue;
                f[u][i]=min(f[u][i],f[v][i+1]-g[v][i]+g[u][i+1]);
            } 
        } 
        
        g[u][0]=f[u][0];//g[u]真正的初始状态 
        for(int i=1;i<=n;i++)//贪心的扫一下g[u] 
            g[u][i]=min(g[u][i],g[u][i-1]);
    }
    
    int main(){
        cin>>n;
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u); 
        }
        
        dfs(1,1);
        
        cout<<f[1][0]<<'
    ';
    } 
  • 相关阅读:
    通过ADB命令查看当前Android运行程序的页面信息
    C#中发起GET和POST请求的方法
    CocoaPods使用
    Carthage使用
    Mac终端常用命令和操作
    Mac OS环境变量配置
    Mac OS包管理器Homebrew
    js利用localStroage实现一个页面栈
    vue-cli快速搭建Vue脚手架 (vue-cli 3.x 模板)
    yarn和npm常用命令
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12594507.html
Copyright © 2020-2023  润新知