• Codeforces Round #383 (Div. 2)D. Arpa's weak amphitheater and Mehrdad's valuable Hoses(dp背包+并查集)


    题目链接 :http://codeforces.com/contest/742/problem/D

    题意:给你n个女人的信息重量w和美丽度b,再给你m个关系,要求邀请的女人总重量不超过w

    而且如果邀请了一个女人要么就邀请她一个,要么要邀请她还有她所有的朋友。

    很明显是一道并查集+背包的问题,并不难。要注意的是背包的写法,由于选择情况有两种

    1)只选一个女人

    2)选和这个女人有关系的一群女人

    于是背包最外层是关系数,即联通块的个数,次外层是背包大小,内层是联通个数(由于选择的要求在一个联通块中

    只能选择一个或者全选所以背包大小要放在联通个数外面,毕竟只要选一次)然后就没然后了

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int M = 1010;
    const int inf = 0X3f3f3f3f;
    int wi[M] , be[M];
    vector<int> vc , fr[M];
    long long dp[M];
    int temp , counts;
    int fa[M] , n , m , w;
    void init() {
        for(int i = 0 ; i <= n ; i++) {
            fa[i] = i;
        }
    }
    int getf(int x) {
        if(x != fa[x])
            fa[x] = getf(fa[x]);
        return fa[x];
    }
    void Union(int x , int y) {
        int xx = getf(x);
        int yy = getf(y);
        if(xx != yy) {
            fa[xx] = yy;
        }
    }
    void dfs(int pos) {
        for(int i = 1 ; i <= n ; i++) {
            int father = getf(i);
            if(father == pos) {
                fr[temp].push_back(i);
            }
        }
    }
    int main() {
        cin >> n >> m >> w;
        init();
        for(int i = 1 ; i <= n ; i++) {
            cin >> wi[i];
        }
        for(int i = 1 ; i <= n ; i++) {
            cin >> be[i];
        }
        for(int i = 1 ; i <= m ; i++) {
            int x , y;
            cin >> x >> y;
            Union(x , y);
        }
        memset(dp , 0 , sizeof(dp));
        temp = 0;
        for(int i = 1 ; i <= n ; i++) {
            if(fa[i] == i) {
                vc.push_back(i);
            }
        }
        int L = vc.size();
        for(int i = 0 ; i < L ; i++) {
            temp++;
            dfs(vc[i]);
        }
        for(int i = 1 ; i <= temp ; i++) {
            int len = fr[i].size();
            int sum1 = 0 , sum2 = 0;
            for(int j = 0 ; j < len ; j++) {
                int p = fr[i][j];
                sum1 += wi[p];
                sum2 += be[p];
            }
            for(int l = M - 2 ; l >= 0 ; l--) {
                if(l + sum1 < M) {
                    dp[l + sum1] = max(dp[l + sum1] , dp[l] + sum2);
                }
                for(int j = 0 ; j < len ; j++) {
                    int p = fr[i][j];
                    if(l + wi[p] < M) {
                        dp[l + wi[p]] = max(dp[l + wi[p]] , dp[l] + be[p]);
                    }
                }
            }
        }
        long long MAX = 0;
        for(int i = 0 ; i <= w ; i++) {
            MAX = max(MAX , dp[i]);
        }
        cout << MAX << endl;
        return 0;
    }
    
    
  • 相关阅读:
    overflow+文档流
    《大器晚成》读后感 读书笔记
    《指标陷阱》读后感 读书笔记
    《无限的游戏》读后感 读书笔记
    《最蓝的眼睛》读后感 读书笔记
    《正常人》读后感 读书笔记
    《玉米人》读后感 读书笔记
    《科举史》读后感 读书笔记
    《糖的故事》读后感 读书笔记
    《蒙克传》读后感 读书笔记
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6140936.html
Copyright © 2020-2023  润新知