西安邀请赛-D(带权并查集+背包)
题目链接:https://nanti.jisuanke.com/t/39271
题意:给定n个物品,m组限制,每个物品有个伤害值,现在让两个人取完所有物品,要使得两个人取得物品伤害值之和最接近,输出伤害值不小于另一个的人的伤害值,每组限制包括两次数x y,表示物品x和物品y不能由同一个人取得。
思路:思路是通过bfs或并查集将有关系的物品合并为一个物品,合并的物品有两个值,每个人必须分别取每个物品的一个值,然后就是背包问题了。
具体实现就是用root[i]表示i的祖先,a[i]表示i与其祖先的关系(为0表示和祖先放在一边,为1表示和祖先不能放一边),可以得到(x->z=(x->y)^(y->z),x->z表示物品x,z的关系,还有x->y=y->x),然后就可以通过并查集来维护所有限制关系。之后遍历所有祖先等于自己的个数,即合并后的连通块个数,设为k。然后把第i个集合中和与祖先关系为0的都加在b[i][0]上,把第i个集合中和祖先关系为1的都加在b[i][1]上。然后还有个操作就是因为每个人分别取b[i][0],b[i][1]中的一个,要使差值最小,那么可以将b[i][0],b[i][1]同时减一个数使得min(b[i][0],b[i][1])=0,这并不影响答案。这样就是减去min(b[i][0],b[i][1])=0,剩下那个非0的数存进d[i]中,并且将所有d[i]加起来得到sum1。
那么问题就转换为有k个物体,价值为d[i],这里价值和体积一样,在空间为sum/2的背包中,每次有选或不选两种可能,求背包最大的价值为多少。然后就可以得到结果了。说的有点绕,但思路不复杂,理解一下自己写写,代码写得有点乱,不建议看。。
AC代码:
#include<cstdio>
#include<map>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std; int T,n,m,sum1,sum2,sum3,sum4,c[],root[],a[];
int b[][],d[],dp[]; int getr(int k){
if(root[k]==k) return k;
else{
int tmp=root[k];
root[k]=getr(root[k]);
a[k]^=a[tmp];
return root[k];
}
} int main(){
scanf("%d",&T);
while(T--){
memset(b,,sizeof(b));
memset(d,,sizeof(d));
memset(dp,,sizeof(dp));
sum1=,sum2=,sum3=;
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)
root[i]=i,a[i]=;
for(int i=;i<=n;++i)
scanf("%d",&c[i]),c[i]/=,sum1+=c[i];
while(m--){
int x,y,rx,ry;
scanf("%d%d",&x,&y);
rx=getr(x),ry=getr(y);
if(rx==ry) continue;
root[ry]=rx;
a[ry]=^a[y]^a[x];
}
map<int,int> mp;
int k=;
for(int i=;i<=n;++i)
if(getr(i)==i)
mp[i]=++k;
for(int i=;i<=n;++i){
int r=getr(i);
b[mp[r]][a[i]]+=c[i];
}
for(int i=;i<=k;++i)
d[i]=abs(b[i][]-b[i][]),sum2+=d[i],sum3+=min(b[i][],b[i][]);
sum4=sum2/;
for(int i=;i<=k;++i)
for(int j=sum4;j>=d[i];--j)
dp[j]=max(dp[j],dp[j-d[i]]+d[i]);
printf("%d\n",(sum1-(sum3+dp[sum4]))*);
}
return ;
}
西安邀请赛-D(带权并查集+背包)的更多相关文章
- poj1417 带权并查集 + 背包 + 记录路径
True Liars Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 2713 Accepted: 868 Descrip ...
- poj1417(带权并查集+背包DP+路径回溯)
题目链接:http://poj.org/problem;jsessionid=8C1721AF1C7E94E125535692CDB6216C?id=1417 题意:有p1个天使,p2个恶魔,天使只说 ...
- POJ 1703 Find them, Catch them(带权并查集)
传送门 Find them, Catch them Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 42463 Accep ...
- [NOIP摸你赛]Hzwer的陨石(带权并查集)
题目描述: 经过不懈的努力,Hzwer召唤了很多陨石.已知Hzwer的地图上共有n个区域,且一开始的时候第i个陨石掉在了第i个区域.有电力喷射背包的ndsf很自豪,他认为搬陨石很容易,所以他将一些区域 ...
- poj1984 带权并查集(向量处理)
Navigation Nightmare Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 5939 Accepted: 2 ...
- 【BZOJ-4690】Never Wait For Weights 带权并查集
4690: Never Wait for Weights Time Limit: 15 Sec Memory Limit: 256 MBSubmit: 88 Solved: 41[Submit][ ...
- hdu3038(带权并查集)
题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=3038 题意: n表示有一个长度为n的数组, 接下来有m行形如x, y, d的输入, 表示 ...
- 洛谷OJ P1196 银河英雄传说(带权并查集)
题目描述 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦 创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争.泰山 ...
- poj1984 带权并查集
题意:有多个点,在平面上位于坐标点上,给出一些关系,表示某个点在某个点的正东/西/南/北方向多少距离,然后给出一系列询问,表示在第几个关系给出后询问某两点的曼哈顿距离,或者未知则输出-1. 只要在元素 ...
随机推荐
- yii框架学习(安装)
安装yii: 在本地安装前, 要确保PHP配置了环境变量, 通过cmd输入PHP -v 即可检测. 能看到PHP版本号, 则OK. PHP不是内部命令,则需要添加PHP环境变量. 使用compos ...
- 【Python之路】特别篇--Python内置函数
abs() 求绝对值 i = abs(-100) print(i) # 100 all() 循环里面的参数 如果每个元素都为真,那么all返回值为真 假: 0 False None "&q ...
- hadoop安装后运行一个单实例(测试MapReduce程序)
1.安装hadoop 解压hadoop-1.2.1-bin.tar.gz包 tar -zxvf hadoop-1.2.1-bin.tar.gz /opt/modules/ 解压后在/opt/mo ...
- ueditor编辑器+粘贴word
最近公司做项目需要实现一个功能,在网页富文本编辑器中实现粘贴Word图文的功能. 我们在网站中使用的Web编辑器比较多,都是根据用户需求来选择的.目前还没有固定哪一个编辑器 有时候用的是UEditor ...
- URAL 2036 Intersect Until You're Sick of It 形成点的个数 next_permutation()函数
A - Intersect Until You're Sick of It Time Limit:500MS Memory Limit:65536KB 64bit IO Format: ...
- hadoop hdfs hbase优化实例
需求描述: 从hdfs中获取数据,字段url需要计算出url_type 通过进行hive的left outer join ,效率非常低.故将url的类型导入到hbase中,利用hbase快速查询的特点 ...
- 费马小定理证明 (copy的,自己捋清楚)
费马小定理:假如p是质数,且gcd(a,p)=1,那么 a^(p-1)≡1(mod p) 证明(copy的百度百科,加点自己的解释) 引理1. 若a,b,c为任意3个整数,m为正整数,且(m,c)=1 ...
- [题解] [CQOI2007] 余数求和
题面 题解 考虑到这个等式\(a\bmod b = a - b * \lfloor\frac{a}{b}\rfloor\) 所以我们可以得到: \[ \begin{aligned} ans & ...
- DL反向传播理解
作者:寒小阳 时间:2015年12月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/50321873 声明:版权所有,转载请联系作者并注明 ...
- LeetCode 21. 合并两个有序链表(Merge Two Sorted Lists)
题目描述 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出:1->1-& ...