题目链接
题目描述
小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;
}
总结
这道题最大的重点就是要看到题目描述的深层含义,把题目的需求转换为对应的模型。再套用相应的模板即可。