B-经商(并查集+01背包)
B-经商
https://ac.nowcoder.com/acm/problem/14545
题目描述
任务一:
有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; }