zoukankan      html  css  js  c++  java
  • Codeforce 741B Arpa's weak amphitheater and Mehrdad's valuable Hoses(并查集&分组背包)

    题意:

    给定n个价值为b 花费为w的物品, 然后某些物品是属于同一个组的, 给定一个花费限制V, 求在小于等于V的情况下取得到的价值最大为多少,能对于同一个组的物品,要么全取,要么只取一个。

    分析:

    可以采用并查集将所有的集合统计出来, 然后再将集合中所有的价值总和sumb和所有的花费总和sumw也作为一个元素加入集合。然后就是分组背包的做法,目前暂时参考背包九讲。

      

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1007;
    int f[maxn]; //并查集
    int b[maxn], w[maxn];
    int n, W, m;
    void init()
    {
        for(int i = 1; i <= n; i++){
            f[i] = i;
        }
    }
    int Find(int x)
    {
        if( x == f[x])
            return x;
        else {
            f[x] = Find(f[x]);
            return f[x];
        }
    }
    int dp[maxn];
    void Merge(int v , int u)
    {
        int t1,t2;
        t1 = Find(v);
        t2 = Find(u);
        if(t1 != t2){
            f[t2] = t1;
        }
    }
    struct s{
        int w, b;
        s(int _w, int _b) : w(_w), b(_b){};
    };
    vector<s> group[maxn];
    int divgroup()
    {
        for(int i = 1; i <= n;i++)
        {
            group[Find(i)].push_back(s(w[i],b[i]));
        }
        for(int i = 1; i <= n; i++)
        {
            if(!group[i].empty())
            {
                int w_sum = 0, b_sum = 0;
                for(int j = 0; j < group[i].size(); j++){
                    w_sum += group[i][j].w;
                    b_sum += group[i][j].b;
                }
                group[i].push_back(s(w_sum, b_sum));
            }
        }
    }
    int main()
    {
        #if LOCAL
        freopen("1.txt","r",stdin);
        #endif // LOCAL
        scanf("%d %d %d", &n ,&m, &W);
        for(int i = 1; i <= n; i++){
            scanf("%d", &w[i]);
        }
        for(int i = 1; i<= n; i++){
            scanf("%d", &b[i]);
        }
    
        init();
        for(int i = 0; i < m; i++){
            int u, v;
            scanf("%d %d", &u, &v);
            Merge(u,v);
        }
        divgroup();
    
    
        for(int k = 1; k <= n; k++){
            if(!group[k].empty()){
                for(int v = W; v >= 0; v--){
                    for(int i = 0; i < group[k].size(); i++){
                        if(v-group[k][i].w >= 0)
                            dp[v] = max(dp[v], dp[v-group[k][i].w]+ group[k][i].b);
                    }
                }
            }
        }
        printf("%d
    ", dp[W]);
    
        return 0;
    }
  • 相关阅读:
    游遍中国 —— 大街小巷、秘境与远方
    Batch Normalization 反向传播(backpropagation )公式的推导
    Batch Normalization 反向传播(backpropagation )公式的推导
    【社会/人文】概念的理解 —— 断舍离、饭(饭制版)
    【社会/人文】概念的理解 —— 断舍离、饭(饭制版)
    linux 线程的同步 一 (互斥量和信号量)
    linux find
    正则表达式30分钟入门教程-新
    linux sed命令详解 *****
    linux vim tutor
  • 原文地址:https://www.cnblogs.com/Jadon97/p/6924906.html
Copyright © 2011-2022 走看看