• Gym 102222G Factories(贡献+树形dp+01背包)


    链接:https://codeforces.com/gym/102222/problem/G

    题意:给出一个树,从所有的叶子节点中选出m个节点,使得这m个节点间的 sigma(任意2点间的距离)最小。求最小的sigma。 n<1e5, k<100。

    题解:求任意2点间的距离和, 可考虑贡献,考虑每条边对答案的贡献,w*k*(m-k)。对每个子树考虑  dp[u][j]=min(dp[u][j], dp[u][j-k]+dp[v][k]+1ll*w*k*(m-k)),每个子树有siz[v](多少个叶子节点)的节点可取,考虑01背包,注意V枚举的时候逆序。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn=1e5+5;
    const long long inf=1e17+5;
    int n, m;
    int head[maxn], degree[maxn], siz[maxn], tot;
    struct Edge{
        int to, next, val;
    }edge[maxn*2];
    long long dp[maxn][105];
    
    void addedge(int u, int v, int w)
    {
        edge[++tot].to=v, edge[tot].val=w, edge[tot].next=head[u];
        head[u]=tot;
    }
    
    void init_edge()
    {
        tot=0;
        memset(head, -1, sizeof(head));
        memset(degree, 0, sizeof(degree));
        memset(siz, 0, sizeof(siz));
    }
    
    void init_dp()
    {
        for(int i=1; i<=n; i++)
        {
            dp[i][0]=0;
            for(int j=1; j<=m; j++)
                dp[i][j]=inf;
        }
        for(int i=1; i<=n; i++)
            if(degree[i]==1) siz[i]=1, dp[i][1]=0;
    }
    
    void dfs(int u, int pre)
    {
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].to, w=edge[i].val;
            if(v==pre) continue;
            dfs(v, u);
            siz[u]+=siz[v];
            for(int j=min(m, siz[u]); j>=1; j--)  //逆序,背包问题, siz[u]个,每个都是选或者不选
                for(int k=1; k<=min(j, siz[v]); k++)
                    dp[u][j]=min(dp[u][j], dp[u][j-k]+dp[v][k]+1ll*w*k*(m-k));
        }
    }
    
    int main()
    {
        ios::sync_with_stdio(false), cin.tie(0);
        //freopen("in.txt", "r", stdin);
        int T, kase=0;
        for(cin>>T; T--; )
        {
            init_edge();
            int rt=1;
            cin>>n>>m;
            for(int u,v,w,i=1; i<n; i++)
            {
                cin>>u>>v>>w;
                addedge(u, v, w), addedge(v, u, w);
                degree[u]++, degree[v]++;
                if(degree[u]>1) rt=u;
                if(degree[v]>1) rt=v;
            }
            init_dp();
            dfs(rt, 0);
            cout<<"Case #"<<++kase<<": "<<dp[rt][m]<<"
    ";
        }
        return 0;
    }
  • 相关阅读:
    Kubernetes实战模拟三(wordpress健康检查和服务质量QoS)
    Kubernetes实战模拟二(wordpress高可用)
    Kubernetes实战模拟一(wordpress基础版)
    Rook部署测试Ceph和wordpress实战应用
    kettle作业转换的执行
    BUU BURP COURSE 1
    BUU SQL COURSE 1
    BUU CODE REVIEW 1
    查看FGC
    Pod大量为Evicted被驱逐状态
  • 原文地址:https://www.cnblogs.com/Yokel062/p/11947797.html
Copyright © 2020-2023  润新知