1387:搭配购买(buy)

【题目描述】

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

但是Joe的钱有限,所以他希望买的价值越多越好。

【输入】

第1行nmw,表示n朵云,m个搭配,Joe有w的钱。

第2~n+1行,每行cidi表示i朵云的价钱和价值。

第n+2~n+1+m行,每行uivi,表示买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 
#include 
#include 
#include 
#include 
#include 
#include 
#define rush() int T;cin>>T;while(T--)
#define sf(a) scanf("%d\n",&a)
#define sft(a,b) scanf("%d%d",&a,&b)
#define go(a) while(scanf("%d",&a)!=EOF)
#define ms(a,b) memset(a,b,sizeof a)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pf(a) printf("%.8lf",a)
#define E 1e-8
using namespace std;
typedef long long ll;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const int idata=1e4+5;

int n,m,t,f;
int i,j,k;
int fa[idata];
int w[idata],v[idata];
int dp[idata];

int Find(int son)
{
    if(fa[son]!=son) fa[son]=Find(fa[son]);
    return fa[son];
}
void Union(int x,int y)
{
    int nx=Find(x),ny=Find(y);
    if(nx!=ny)
    {
        fa[ny]=nx;
        w[nx]+=w[ny];
        v[nx]+=v[ny];
        /*fa[nx]=ny;
        w[ny]+=w[nx];
        v[ny]+=v[nx];也可以是这个*/
    }
}
int main()
{
    cin.tie(0);
    iostream::sync_with_stdio(false);
    while(cin>>n>>m>>f)
    {
        for(i=1;i<=n;i++) fa[i]=i;
        for(i=1;i<=n;i++)
        {
            cin>>w[i]>>v[i];
        }
        for(i=1;i<=m;i++)
        {
            int x,y;
            cin>>x>>y;
            if(Find(x)!=Find(y)) Union(x,y);
        }
        int cnt=0;
        for(i=1;i<=n;i++)
        {
            if(fa[i]==i)
            {
                v[++cnt]=v[i];
                w[cnt]=w[i];
            }
        }
        for(i=1;i<=cnt;i++)
        {
            for(j=f;j>=w[i];j--)
            {
                dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
            }
        }
        cout<

 

你可能感兴趣的:(信息学奥赛,#,并查集)