题目描述
任务一:
有n个人,每个人只能选一次,会消耗a[i]精力得到b[i]收益,现有的精力值为C,求可以到达的最大收益
思路
这么看就是一个简单的01背包问题(用一维的话注意从大到小枚举c(精力))
任务二
这n个人之间存在友谊关系,我们只能选择跟1有关系的人,
思路
用简单的并查集维护,在01任务1求解的时候判断
if(find(i)!=1) continue;
代码
#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <cstdio>
#include <bitset>
#include <vector>
#include <iomanip>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define UpMing main
#define re register
#pragma GCC optimize(2)
#define Accept return 0;
#define lowbit(x) ((x)&(-(x)))
#define mst(x, a) memset( x,a,sizeof(x) )
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int inf =0x3f3f3f3f;
const int maxn=2e5+7;
const ll mod = 1e9+7;
const int N =1e6+3;
inline ll read() {
ll x=0;
bool f=0;
char ch=getchar();
while (ch<'0'||'9'<ch) f|=ch=='-', ch=getchar();
while ('0'<=ch && ch<='9')
x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
void out(ll x) {
int stackk[20];
if(x<0) {
putchar('-');
x=-x;
}
if(!x) {
putchar('0');
return;
}
int top=0;
while(x) stackk[++top]=x%10,x/=10;
while(top) putchar(stackk[top--]+'0');
}
ll n,m,c,a[maxn],b[maxn],p[maxn],dp[maxn];
ll find(ll x) {
if(x==p[x]) return x;
return p[x]=find(p[x]);
}
int UpMing() {
ll toto=read();
while(toto--) {
n=read();
m=read();
c=read();
for(int i=1 ; i<=1e5 ; i++)
a[i]=b[i]=dp[i]=0,p[i]=i;
for(int i=2 ; i<=n ; i++) {
a[i]=read();
b[i]=read();
}
for(int i=1 ; i<=m ; i++) {
ll x=read();
ll y=read();
ll dx=find(x);
ll dy=find(y);
if(dx>dy) swap(dx,dy);
if(dx!=dy)
p[dy]=dx;
}
for(int i=2 ; i<=n ; i++) {
if(find(i)!=1) continue;
for(int j=c ; j>=a[i]; j--) {
dp[j]=max(dp[j],dp[j-a[i]]+b[i]);
}
}
out(dp[c]);
cout<<endl;
}
Accept;
}
京公网安备 11010502036488号