牛客网Problem14545 B-经商解题报告(并查集)

题目链接
题目描述
小d是一个搞房地产的土豪。每个人经商都有每个人经商的手段,当然人际关系是需要放在首位的。
小d每一个月都需要列出来一个人际关系表,表示他们搞房地产的人的一个人际关系网,但是他的精力有限,对应他只能和能够接触到的人交际。比如1认识2,2认识3,那么1就可以接触3进行交际,当然1和2也可以交际。
小d还很精明,他知道他和谁交际的深获得的利益大,接下来他根据自己的想法又列出来一个利益表,表示他和这些人交际需要耗用多少精力,能够获得的利益值为多少。
小d想知道,他在精力范围内,能够获得的利益值到底是多少。
设定小d自己的编号为1.并且对应一个人的交际次数限定为1.
输入描述
本题包含多组输入,第一行输入一个数t,表示测试数据的组数
每组数据的第一行输入三个数,N,M,C,表示这个人际关系网一共有多少个人,关系网的关系数,以及小d的精力值
接下来N-1行,每行两个数ai,bi。这里第i行表示和编号为i+1的人认识需要花费ai的精力,能够获得的利益值为bi。
再接下来M行,每行两个数x,y,表示编号为x的人能够和编号为y的人接触.
t ≤ \leq 50
2 ≤ \leq N ≤ \leq 10000
1 ≤ \leq M ≤ \leq 10*N
1 ≤ \leq ai,bi ≤ \leq 10
1 ≤ \leq C ≤ \leq 500
1 ≤ \leq x,y ≤ \leq N
输出描述
输出包含一行,表示小d能够获得的最大利益值
示例1
输入

1
5 3 7
5 10
3 2
4 3
1 100
1 2
2 3
1 4

输出
10
题目大意
小d只能和自己的朋友,或者能够通过朋友关系介绍认识的朋友交流,与每一个朋友交流都会损耗对应的精力,但也会得到对应的利益。求某一精力下能够得到的最大利益。
解题思路
这道题先用并查集筛选一下,找到与小d在同一个集合的所有土豪,并用w,v数组记录对应的a[i],b[i]的值,之后就转换为经典的01背包问题。套用01背包的模板即可。

#include <bits/stdc++.h>
#define INF 0x3f3f3f
using namespace std;
const int mod=1e9+7;
const int Max_N=1e4+5;
typedef pair<int,int>P;
typedef long long ll;
typedef unsigned long long ull;
int pre[Max_N];
int find(int x)
{
    int r=x;
    while(r!=pre[r])
    {
        r=pre[r];
    }
    int i=x,j;
    while(i!=pre[i])
    {
        j=pre[i];
        pre[i]=r;
        i=j;
    }
    return r;
}
void join(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy)
        pre[fx]=fy;
}
int main(int argc, char const *argv[])
{
    int t;
    int a[Max_N],b[Max_N];
    scanf("%d",&t);
    while(t--)
    {
        int N,M,C;
        memset(pre,0,sizeof(pre));
        for(int i=0;i<Max_N;i++)
        {
            pre[i]=i;//初始化每个人最开始的父亲为自己
        }
        scanf("%d%d%d",&N,&M,&C);
        for(int i=2;i<=N;i++)
        {
            scanf("%d%d",&a[i],&b[i]);
        }
        for(int i=0;i<M;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            join(x,y);
        }
        int cnt=0;
        int w[Max_N],v[Max_N];
        int fat=find(1);
        for(int i=2;i<=N;i++)
        {
            if(fat==find(i))
            {
                w[cnt]=a[i];
                v[cnt++]=b[i];
            }
        }
        int dp[Max_N];
        memset(dp,0,sizeof(dp));
        for(int i=0;i<cnt;i++)
        {
            for(int j=C;j>=w[i];j--)
            {
                dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
            }
        }//01背包
        printf("%d\n",dp[C]);
    }
    return 0;
}

总结
这道题最大的重点就是要看到题目描述的深层含义,把题目的需求转换为对应的模型。再套用相应的模板即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值