vijos1250 最勇敢的机器人
背景
Wind设计了很多机器人。但是它们都认为自己是最强的,于是,一场比赛开始了~
描述
机器人们都想知道谁是最勇敢的,于是它们比赛搬运一些物品。
它们到了一个仓库,里面有n个物品,每个物品都有一个价值Pi和重量Wi,但是有些物品放在一起会爆炸,并且爆炸具有传递性。(a和b会爆炸、b和c会爆炸则a和c会爆炸)
机器人们可不想因此损失自己好不容易从Wind那里敲诈来的装备,于是它们想知道在能力范围内,它们最多可以拿多少价值的物品。
你能帮助它们吗?
格式
输入格式
每组测试数据
第1行为n,Wmax,k(0<=n,Wmax,k<=1000)
接下来n行,为每个物品的Pi,Wi(0<=Pi<=1000,1<=Wi<=10,均为整数)
再接下来k行,每行2个数字a,b表示a和b会发生爆炸
输出格式
对每组数据输出1行
为最大可能价值
/* 并查集分组,分组背包 */ #include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int maxn = 1005; struct ITM{ int v; int w; }temp; int n,c,k,f[maxn],v[maxn],w[maxn],dp[maxn]; int u1,u2,r; int cnt,tran[maxn],now; bool vis[maxn]; vector<ITM> itm[maxn]; int findf(int x){ return x == f[x] ? x : f[x] = findf(f[x]); } int read(){ char ch=getchar(); int f=1,x=0; while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}; while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}; return x*f; } int main(){ n = read(); c = read(); k = read(); for(int i = 1;i <= n;i++) f[i] = i; for(int i = 1;i <= n;i++){ v[i] = read(); w[i] = read(); } for(int i = 1;i <= k;i++){ u1 = read(); u2 = read(); u1 = findf(u1); u2 = findf(u2); if(u1 != u2) f[u1] = u2; } for(int i = 1;i <= n;i++){ r = findf(i); temp.v = v[i]; temp.w = w[i]; itm[r].push_back(temp); if(!vis[r]){ vis[r] = true; cnt++; tran[cnt] = r; } } for(int i = 1;i <= cnt;i++){ now = tran[i]; for(int j = c;j >= 0;j--){ for(int t = 0;t < itm[now].size();t++){ if(j >= itm[now][t].w)dp[j] = max(dp[j],dp[j-itm[now][t].w] + itm[now][t].v); } } } cout<<dp[c]; return 0; }