CF741B Arpa's weak amphitheater and Mehrdad's valuable Hoses 并查集 01背包

title

CF741B

简化题意:

有 \(n\) 个人 \((1<=n<=1000)\) ,每个人有一个重量 \(w_i(1\leqslant w_i\leqslant 1000)\) 和一个魅力值 \(b_i(1\leqslant b_i\leqslant 10^6)\) 。

\(n\) 个人之间有 \(m(1\leqslant m\leqslant min(\frac{n(n-1)}{2}, 10^5))\) 个关系。第 \(i\) 个关系由两个数字 \(x_i\) 和 \(y_i\) 组成,表示第 \(x_i\) 个人和第 \(y_i\) 个人是朋友,朋友关系是双向的。

已知若 \(a\) 和 \(b\) 是朋友, \(b\) 和 \(c\) 是朋友,则 \(a\) 和 \(c\) 是朋友。 现在 \(Mehrdad\) 要邀请一些人来到派对,使这些人的重量总和不超过 \(w_i(1\leqslant w_i\leqslant 1000)\) ,且魅力值总和尽量大。同一个朋友圈里的人,只能邀请其中的一个人,或者全部人,或者一个人也不邀请。

analysis

  1. 确定哪些人在同一组,这样的话就想到了并查集。然后利用 \(vector\) 容器将同一组的人存放在一起。
  2. 按上面的要求对于每个容器中的人要么全部都取,要么只取一个,要么不取,那么这其实就是一个简单的 \(01\) 背包问题了。
  3. 所以这道题就解决了,提智商!

code

#include<bits/stdc++.h>

#define file(s) freopen(s".in","r",stdin), freopen(s".out","w",stdout)

#define G ch=getchar()
#define DeBug(x) std::cout<<#x<<':'<<x<<std::endl

const int MaxN=1e3+10;

namespace IO
{
    char buf[1<<15],*fs,*ft;
    inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
    template<typename T>inline void read(T &x)
    {
        x=0;
        T f=1, G;
        while (!isdigit(ch) && ch^'-') G;
        if (ch=='-') f=-1, G;
        while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), G;
        x*=f;
    }

    char Out[1<<24],*fe=Out;
    inline void flush() { fwrite(Out,1,fe-Out,stdout); fe=Out; }
    template<typename T>inline void write(T x,char str)
    {
        if (!x) *fe++=48;
        if (x<0) *fe++='-', x=-x;
        T num=0, ch[20];
        while (x) ch[++num]=x%10+48, x/=10;
        while (num) *fe++=ch[num--];
        *fe++=str;
    }
}

using IO::read;
using IO::write;

template<typename T>inline bool chkMin(T &a,const T &b) { return a>b ? (a=b, true) : false; }
template<typename T>inline bool chkMax(T &a,const T &b) { return a<b ? (a=b, true) : false; }
template<typename T>inline T min(T a,T b) { return a<b ? a : b; }
template<typename T>inline T max(T a,T b) { return a>b ? a : b; }

namespace Union_Set
{
    int fa[MaxN];
    inline int get(int x)
    {
        return fa[x]==x ? x : fa[x]=get(fa[x]);
    }

    inline void merge(int x, int y)
    {
        int fx=get(x), fy=get(y);
        if (fx^fy) fa[fx]=fy;
    }
}

using Union_Set::get;
using Union_Set::merge;

int w[MaxN], b[MaxN], f[MaxN];
std::vector<int> g[MaxN];
int main()
{
    int n, m, W;
    read(n), read(m), read(W);//总重
    for (int i=1; i<=n; ++i) read(w[i]);//重量
    for (int i=1; i<=n; ++i) read(b[i]);//魅力值

    for (int i=1; i<=n; ++i) Union_Set::fa[i]=i;
    for (int i=1, x, y; i<=m; ++i) read(x), read(y), merge(x, y);

    for (int i=0; i<MaxN; ++i) g[i].clear();
    for (int i=1; i<=n; ++i) g[get(i)].push_back(i);

    memset(f, 0, sizeof(f));
    for (int i=1; i<=n; ++i)
    {
        if (get(i)^i) continue;//一个人也不邀请
        for (int j=W; j>=0; --j)
        {
            int sumw=0, sumb=0;
            for (int k=0; k<(int)g[i].size(); ++k)//或者只能邀请其中的一个人
            {
                sumw+=w[g[i][k]], sumb+=b[g[i][k]];
                if (j>=w[g[i][k]]) chkMax(f[j], f[j-w[g[i][k]]]+b[g[i][k]]);
            }
            if (j>=sumw) chkMax(f[j], f[j-sumw]+sumb);//或者全部人
        }
    }
    write(f[W], '\n');
    IO::flush();
    return 0;
}

CF741B Arpa's weak amphitheater and Mehrdad's valuable Hoses 并查集 01背包

原文地址:https://www.cnblogs.com/G-hsm/p/CF741B.html

时间: 2024-08-28 00:41:15

CF741B Arpa's weak amphitheater and Mehrdad's valuable Hoses 并查集 01背包的相关文章

并查集+背包 【CF741B】 Arpa&#39;s weak amphitheater and Mehrdad&#39;s valuable Hoses

Descirption 有n个人,每个人都有颜值bi与体重wi.剧场的容量为W.有m条关系,xi与yi表示xi和yi是好朋友,在一个小组. 每个小组要么全部参加舞会,要么参加人数不能超过1人. 问保证总重量不超过W,剧场中的颜值最大能到多少? Input 第一行,三个整数n,m,w 第二行,n个整数w1,w2,...,wn 第三行,n个整数b1,b2,...,bn 接下来m行,每行表示一个关系,第i行有两个整数xi和yi. 每一组朋友关系都是不同的. Output ?一行,表示最大的魅力值总和.

Arpa&#39;s weak amphitheater and Mehrdad&#39;s valuable Hoses CodeForces - 742D

Just to remind, girls in Arpa's land are really nice. Mehrdad wants to invite some Hoses to the palace for a dancing party. Each Hos has some weight wi and some beauty bi. Also each Hos may have some friends. Hoses are divided in some friendship grou

D. Arpa&#39;s weak amphitheater and Mehrdad&#39;s valuable Hoses 分组背包模板题

http://codeforces.com/problemset/problem/742/D 并查集预处理出所有关系. 一开始的时候,我预处理所有关系后,然后选择全部的时候,另起了一个for,然后再判断. 这样是不对的.因为这样使得同一组里面可能选择了两次. 3 0 2 1 2 3 1 1 3 #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include &

http://codeforces.com/contest/741/problem/B B. Arpa&#39;s weak amphitheater and Mehrdad&#39;s valuable Hoses

题意: 给出上限体重W 然后还给出每个人的体重wi 和 魅力值 bi 互为伙伴的对(xi, yi) 可以凑成group 思路: 并查集找出所有的group 暴力背包 对于每一个group 要选出这一组内选一个人时的最优结果, 如果所有人的体重和小于等于W,还得考虑选所有人的情况 #include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> #include &l

Codeforces 741B Arpa&#39;s weak amphitheater and Mehrdad&#39;s valuable Hoses

[题目链接] http://codeforces.com/problemset/problem/741/B [题目大意] 给出一张图,所有连通块构成分组,每个点有价值和代价, 要么选择整个连通块,要么只能在连通块中选择一个,或者不选,为最大价值 [题解] 首先我们用并查集求出连通块,然后对连通块进行分组背包即可. [代码] #include <cstdio> #include <vector> #include <algorithm> #include <cstr

codeforces 742D Arpa&#39;s weak amphitheater and Mehrdad&#39;s valuable Hoses ——(01背包变形)

题意:给你若干个集合,每个集合内的物品要么选任意一个,要么所有都选,求最后在背包能容纳的范围下最大的价值. 分析:对于每个并查集,从上到下滚动维护即可,其实就是一个01背包= =. 代码如下: 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <vector> 5 using namespace std; 6 const int N = 1000 + 5;

#383 Div1 Problem B Arpa&#39;s weak amphitheater.... (分组背包 &amp;&amp; 并查集)

题意 : 有n个人,每个人都有颜值bi与体重wi.剧场的容量为W.有m条关系,xi与yi表示xi和yi是好朋友,在一个小组. 每个小组要么全部参加舞会,要么参加人数不能超过1人. 问保证总重量不超过W,剧场中的颜值最大能到多少? 分析 : 很显然的分组背包题目, 不过有所不同, 先来回顾一下普通的分组背包的描述 给出一个背包,背包有容量C,再给出N组物品,每组物品有ki种,每种物品有对应的体积Vi,价值Pi,每组物品至多选一种,且最多取一件.求用背包装物品,能获得的最大总价值是多少.可以发现和上

cfodeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

题目链接:Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths 第一次写\(dsu\ on\ tree\),来记录一下 \(dsu\ on\ tree\)主要维护子树信息,往往可以省掉一个数据结构的启发式合并.大体思路如下: 轻重链路径剖分之后,对每个点先递归处理他的所有轻儿子,每次处理完轻儿子之后把这棵子树的信息清空.最后再来处理重孩子,重儿子的信息就可以不用清空了.由于我们是用一个全局数组来记录信息的,重儿子子树的信息就仍然保留

Codeforces 741 D - Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

D - Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 思路: 树上启发式合并 从根节点出发到每个位置的每个字符的奇偶性记为每个位置的状态,每次统计一下每个状态的最大深度 为了保证链经过当前节点u,我们先计算每个子树的答案,再更新子树状态对深度的贡献. 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bit