poj1417 带权并查集+0/1背包
题意:有一个岛上住着一些神和魔,并且已知神和魔的数量,现在已知神总是说真话,魔总是说假话,有 n 个询问,问某个神或魔(身份未知),问题是问某个是神还是魔,根据他们的回答,问是否能够确定哪些是神哪些是魔。
对于这些问题,我们只需要发现,如果回答对方是魔,那么即可以判断出这两个不是同一种族,而如果回答对方是神,那么说明这两个是同一种族,那么就可以用带权并查集合并这些神和魔,然后记录两种分别多少个,这样当所有询问都处理完时我们就可以得到一系列的集合,每个集合分别有它的两个种族的人数,但是此时对于每个集合,这两个人数我们并不知道分别哪个是神哪个是魔,这时候就需要用到0/1背包的方法, dp[i][j] 代表处理到第 i 个集合时共 j 个人数(神或魔)的情况数,它从 dp[i-1][j-num1[i]] 和 dp[i-1][j-num2[i]] 转移过来,这里 num1、num2 就是一个并查集的两种人数。转移时顺便记录它是从哪个值转移过来的,便于最后输出。这样只要最后处理完所有集合时正好神的人数或魔的人数的情况正好是一种,那么就说明可行。按照记录的转移遍历回去输出所有解就行。加了个小优化就是当某个集合的两种数量相等的时候,直接可以判断否,因为这时这两个数量等效。
#include<stdio.h>
#include<string.h> int fa[],num[],n,num1[],num2[],p[],dp[][],fat[][],num3[];
int p1,p2;
char s[]; int mmax(int a,int b){
return a>b?a:b;
} void init(){
for(int i=;i<=p1+p2;i++){
fa[i]=i;
num1[i]=;
}
memset(num,,sizeof(num));
memset(num2,,sizeof(num2));
} int find(int x){
int r=x,t1,t2,c=;
while(r!=fa[r]){
c+=num[r];
r=fa[r];
}
while(r!=x){
t1=fa[x];
t2=c-num[x];
num[x]=c%;
fa[x]=r;
x=t1;
c=t2;
}
return r;
} int main(){
while(scanf("%d%d%d",&n,&p1,&p2)!=EOF&&n!=||p1!=||p2!=){
int i;
init();
for(i=;i<=n;i++){
int a,b,v;
scanf("%d%d%s",&a,&b,s);
if(s[]=='y')v=;
else v=;
int x=find(a),y=find(b);
if(x!=y){
num[x]=((num[b]+v-num[a])%+)%;
if(num[x]==){
num1[y]+=num1[x];
num2[y]+=num2[x];
}
else{
num1[y]+=num2[x];
num2[y]+=num1[x];
}
fa[x]=y;
}
}
bool f=;
if(p1==p2)printf("no\n");
else{
int cnt=,j;
for(i=;i<=p1+p2;i++){
if(fa[i]==i){
p[++cnt]=i;
if(num1[i]==num2[i])f=;
}
}
if(f){
memset(dp,,sizeof(dp));
dp[][]=;
for(i=;i<=cnt;i++){
for(j=;j<=p1;j++){
if(dp[i-][j]){
dp[i][j+num1[p[i]]]+=dp[i-][j];
fat[i][j+num1[p[i]]]=j;
dp[i][j+num2[p[i]]]+=dp[i-][j];
fat[i][j+num2[p[i]]]=j;
}
}
}
if(dp[cnt][p1]!=)f=;
}
if(!f)printf("no\n");
else{
int father=p1;
for(i=cnt;i>=;i--){
if(father-fat[i][father]==num1[p[i]]){
num3[p[i]]=;
}
else num3[p[i]]=;
father=fat[i][father];
}
for(i=;i<=p1+p2;i++){
int x=find(i);
if(num[i]==num3[x])printf("%d\n",i);
}
printf("end\n");
}
}
}
return ;
}
poj1417 带权并查集+0/1背包的更多相关文章
- 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][ ...
- 洛谷OJ P1196 银河英雄传说(带权并查集)
题目描述 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦 创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争.泰山 ...
- poj1611 带权并查集
题意:病毒蔓延,现在有 n 个人,其中 0 号被认为可能感染,然后给出多个社交圈,如果某个社交圈里有人被认为可能被感染,那么所有这个社交圈里的人都被认为可能被感染,现在问有多少人可能被感染. 带权并查 ...
- hdu 1829-A Bug's LIfe(简单带权并查集)
题意:Bug有两种性别,异性之间才交往, 让你根据数据判断是否存在同性恋,输入有 t 组数据,每组数据给出bug数量n, 和关系数m, 以下m行给出相交往的一对Bug编号 a, b.只需要判断有没有, ...
随机推荐
- RPI学习--环境搭建_更新firmware
(用以解决USB摄像头不识别的状况) rpi-update是老外开发的一个更新树莓派firmware的工具 $ sudo apt-get update $ sudo apt-get install ...
- php操作文件(读取写入文件)
一,PHP如何读取文件 PHP读取文件可以读取当前服务器或远程服务器中的文件.其步骤是:打开文件.读文件和关闭文件. 1,PHP如何打开文件 使用PHP函数fopen()打开一个文件,fopen()一 ...
- 使用WebClient Post方式模拟上传文件和数据
假如某网站有个表单,例如(url: http://localhost/login.aspx):帐号 密码 我们需要在程序中提交数据到这个表单,对于这种表单,我们可以使用 WebClient.Uplo ...
- AFNETWorking3.x实战教程
上一篇文章介绍了优秀的第三方网络请求框架AFNETWorking2.0,本篇就通过一个实战例子来总结AFNetworking的使用. 本文参考http://www.raywenderlich.com/ ...
- Nginx 缓存参数
看看这下面两个指令参数: ----------------------------------------------------------------- proxy_cache_path /ho ...
- 有关PHP的字符串知识
字符串是由一系列字符组成,在PHP中,字符和字节一样,也就是说,一共有256种不同字符的可能性. 字符串型可以用三种方法定义:单引号形式.双引号形式和Heredoc结构形式. 1.每条指令可要记得使用 ...
- ubuntu 输入时弹出剪切板候选项
fcitx很坑的把这个功能的快捷键设置成了ctrl + ;结果我在用vim的时候怎么也 没法输入command 不知道是哪次更新引入的,简直是坑人! 我找了半天系统设置都没找到这个快捷键是在哪设置的. ...
- 三极管的妙用之C118自动刷机
首先咱们要搞清楚咱们自动刷机的原理,不谈修改固件那么高深的东西,简单的就是控制开机键. 使用继电器来控制基本上算是上个世纪的想法吧,之前博主也做过,做出来的感觉其实也很不错,就像是一个收藏品.因为继电 ...
- linux 下安装rsync
一.服务器端配置: 1.安装xinetd,并修改rsync相关配置 # yum -y install xinetd # vi /etc/xinetd.d/rsync 如下代码: service rsy ...
- Linux下查看每个目录所占用空间大小的命令
cd到上级目录,然后输入一条命令即可查询每个子目录所占用的空间大小 du -h --max-depth=1 可以更改--max-depth参数的值,该参数表示查询子目录的层级,当前为1层