搭配购买——并查集+01背包

Joe觉得云朵很美,决定去山上的商店买一些云朵。
商店里有 n 朵云,云朵被编号为 1,2,…,n,并且每朵云都有一个价值。但是商店老板跟他说,一些云朵要搭配来买才好,所以买一朵云则与这朵云有搭配的云都要买。但是Joe的钱有限,所以他希望买的价值越多越好。

输入格式
第 1 行包含三个整数 n,m,w,表示有 n 朵云,m 个搭配,Joe有 w 的钱。
第 2∼n+1 行,每行两个整数 ci,di 表示 i 朵云的价钱和价值。
第 n+2∼n+1+m 行,每行两个整数 ui,vi,表示买 ui 就必须买 vi,同理,如果买 vi 就必须买 ui。

输出格式
一行,表示可以获得的最大价值。

数据范围
1≤n≤10000,0≤m≤5000,1≤w≤10000,1≤ci≤5000,1≤di≤100,1≤ui,vi≤n

输入样例:
5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2

输出样例:
1

解析:

搭配的都要买,可以理解成将有关系的都放在一起,相当一个物品,要买一起买。

这样就可以转换成01背包问题,每个物品只能购买一次,在有限的钱的情况下,让买的物品的价值尽可能的大。

#include 
using namespace std;
#define int long long
const int N=2e6+10;
int p[N];
int v[N],w[N];
int v1[N],w1[N];
int f[N];
bool vis[N];
int find(int x)
{
    if (x!=p[x]) p[x]=find(p[x]);
    return p[x];
}
signed main()
{
    int n,m,k;
    cin>>n>>m>>k;
    for (int i=1;i<=n;i++) p[i]=i;
    for (int i=1;i<=n;i++) cin>>v[i]>>w[i];
    for (int i=0;i>a>>b;
        int x=find(a),y=find(b);
        if (x!=y)
        {
            v[y] +=v[x];
            w[y] +=w[x];
            p[x]=y;
        }
    }
    int cnt=0;
    for (int i=1;i<=n;i++)
    {
        int x=find(i);
        if (!vis[x])
        {
            cnt++;
            v1[cnt]=v[x];
            w1[cnt]=w[x];
            vis[x]=1;
        }
    }
    for (int i=1;i<=cnt;i++)       //01背包最简化  //模板
    for (int j=k;j>=v1[i];j--)
    f[j]=max(f[j],f[j-v1[i]]+w1[i]);
    cout<
using namespace std;
#define int long long
const int N=2e6+10;
int p[N];
int v[N],w[N];
int f[N];
int find(int x)
{
    if (x!=p[x]) p[x]=find(p[x]);
    return p[x];
}
signed main()
{
    int n,m,k;
    cin>>n>>m>>k;
    for (int i=1;i<=n;i++) p[i]=i;
    for (int i=1;i<=n;i++) cin>>v[i]>>w[i];
    for (int i=0;i>a>>b;
        int x=find(a),y=find(b);
        if (x!=y)
        {
            v[y] +=v[x];
            w[y] +=w[x];
            p[x]=y;
        }
    }
    for (int i=1;i<=n;i++)       //01背包最简化  //模板
    if (p[i]==i)                 //每个集合的根节点
    {
        for (int j=k;j>=v[i];j--)
        f[j]=max(f[j],f[j-v[i]]+w[i]);
    }
    cout<

你可能感兴趣的:(算法)