並查集+01揹包 1387:搭配購買(buy)

【題目描述】
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。

【輸出】
一行,表示可以獲得的最大價值。

【輸入樣例】
5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2
【輸出樣例】
1
【提示】
【數據範圍】

30%的數據保證:n≤100;

50%的數據保證:n≤1,000;m≤100;w≤1,000;

100%的數據保證:n≤10,000;0≤m≤5000;w≤10,000。

#include <bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define PII pair<int,int>

using namespace std;
const int N=1e4+5;
int n,m,w,fa[N],u,v,dp[N];
struct node
{
    int x,y;
}a[N];

int Find(int x)
{
    if(fa[x]!=x)
        fa[x]=Find(fa[x]);
    return fa[x];
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m >> w;
    for(int i=1;i<=n;i++)
    {
        fa[i]=i;
        cin >> a[i].x >> a[i].y;
    }
    while(m--)
    {
        cin >> u >> v;
        int x=Find(u),y=Find(v);
        if(x!=y)
        {
            fa[x]=y;
            a[y].x+=a[x].x;
            a[y].y+=a[x].y;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(i==fa[i])//或if(i==Find(i))
        {
            for(int j=w;j>=a[i].x;j--)
                dp[j]=max(dp[j],dp[j-a[i].x]+a[i].y);
        }
    }
    cout << dp[w] << endl;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章