搭配购买

Problem Description
Joe觉得云朵很美,决定去山上的商店买一些云朵。商店里有n朵云,云朵被编号为1,2,...,n,并且每朵云都有一个价值。但是商店老板跟他说,一些云朵要搭配来买才好,所以买一朵云则与这朵云有搭配的云都要买。但是Joe的钱有限,所以他希望买的价值越多越好。
Input
输入有多组数据,每组数据第1行n(<=10000)、m(>=5000)、w(<=10000),表示n朵云,m个搭配,Joe有w的钱。
第2至n+1行,每行ci、di表示i朵云的价钱和价值。
第n+2至n+1+m行,每行ui、vi表示买ui就必须买vi,同理,如果买vi就必须买ui。
Output
对于每组数据,输出一行,表示可以获得的最大价值。
Sample Input
5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2
Sample Output
1
//关键字:并查集+01背包
//标程:
#include 
#include 
#include 
using namespace std;
struct item
{
    int price, val;
}p[10010], a[10010];
int father[10010], dp[10010];
int findx(int x)
{
    return father[x] == x ? x : father[x];
}
void _union(int u,int v)
{
    u = findx(u);
    v = findx(v);
    father[u] = v;
    a[v].price += a[u].price;
    a[v].val += a[u].val;
}
int main()
{
//    freopen("a.txt","r",stdin);
    int n, m, w, i, j;
    while(scanf("%d%d%d",&n,&m,&w)!=EOF)
    {
        for(i = 1; i <= n; ++ i)
            scanf("%d%d",&p[i].price,&p[i].val);
        for(i = 1; i <= n; ++ i)
        {
            father[i] = i;
            a[i] = p[i];
        }
        int u, v;
        for(i = 1; i <= m; ++ i)
        {
            scanf("%d%d",&u,&v);
            _union(u,v);
        }
        memset(dp,0,sizeof(dp));
        for(i = 1; i <= n; ++ i)
            if(father[i] == i)
            {
                for(j = w; j >= a[i].price; j --)
                    dp[j] = max(dp[j],dp[j-a[i].price] + a[i].val);
            }
        printf("%d\n",dp[w]);
    }
    return 0;
}

你可能感兴趣的:(并查集)