codeforces 741B

来源:互联网 发布:山西省网络文学院 编辑:程序博客网 时间:2024/06/05 11:06

题目大意:

    有n个人,每个人都有对应的value值和weight值, 并且每个人都有自己的朋友圈,这个朋友圈的人要不全部参加party,否则至多只有一个人可以参加;

题目分析:

    分组背包,顺带处理所有人都参加的情况; 

     一个朋友圈就是一个分组,使用并查集可以很简单的完成分组的过程;

代码如下:

#include <bits/stdc++.h>using namespace std;const int maxn = 1005;int n, m, W;int w[maxn], v[maxn], d[maxn], p[maxn];vector<int> iv[maxn];int sw[maxn], sv[maxn]; // 表示每一组的总和重量和总和价值;void init(){    for(int i = 0; i < n; ++i) p[i] = i;    for(int i = 0; i < n; ++i) iv[i].clear();    memset(d, 0, sizeof(d));    memset(sw, 0, sizeof(sw));    memset(sv, 0, sizeof(sv));}int Find(int x){    return x == p[x] ? x : p[x] = Find(p[x]);}void Union(int x, int y){    int xRoot = Find(x), yRoot = Find(y);    p[xRoot] = yRoot;}int main(){    scanf("%d%d%d", &n, &m, &W);    for(int i = 0; i < n; ++i) scanf("%d", &w[i]);    for(int i = 0; i < n; ++i) scanf("%d", &v[i]);    init();    for(int i = 0; i < m; ++i){        int u, v;        scanf("%d%d", &u, &v);        u--, v--;        Union(u, v);    }    for(int i = 0; i < n; ++i){        Find(i);        iv[p[i]].push_back(i);    }    for(int i = 0; i < n; ++i){  // 记录每组的总重和总值;        for(int j = 0; j < (int)iv[i].size(); ++j){            int id = iv[i][j];            sw[i] += w[id], sv[i] += v[id];        }    }    for(int i = 0; i < n; ++i){        if(i!=p[i]) continue;        for(int j = W; j >= 0; --j){            for(int k = 0; k < (int)iv[i].size(); ++k){  //分组背包;                int id = iv[i][k];                if(j-w[id] >= 0)                    d[j] = max(d[j], d[j-w[id]]+v[id]);            }            if(j-sw[i] >= 0){   // 处理所有人都参加的情况;                d[j] = max(d[j], d[j-sw[i]]+sv[i]);            }        }    }    printf("%d\n", d[W]);}


   

0 0
原创粉丝点击