题目链接:http://poj.org/problem;jsessionid=8C1721AF1C7E94E125535692CDB6216C?id=1417

题意:有p1个天使,p2个恶魔,天使只说真话,恶魔只说假话。问n句话,问x:y是否为天使,x回答yes或no,分别表示是或否,问能否确认为天使的人的编号(1..p1+p2),若能按顺序1输出,否则输出no。

思路:

看到带权并查集的题首先考虑到向量,先分析一下,不访设x->y表示x说y是什么,0表示天使,1表示是恶魔,枚举一下会发现x->y=0也表示x y同类,=1表示x y异类。并且x->z=(x->y)^(y->z)。这样就很清晰了,我们使用并查集将有关系的人并起来,并得到每个人与其祖先的关系,这样之后就会得到一些集合,每个集合有两类人。我想到这了就不知道怎么做了,因为我是在刷bin巨并查集专题看到的这题,我的潜意识就是怎么用并查集去解决这个问题,所以我一直在想是不是有其他的并查集的方法。看了别人的博客才恍然大悟之后就是一个完全背包的题了啊。还是太年轻了,思维应该开阔些,不能局限在一种思维上去想怎么做题。

回到题目,利用并查集得到这些集合比较简单,稍微熟悉并查集都能想到,接下来的背包DP和路径回溯才是这道题的核心。先遍历一遍用r[i]表示第i个集合的祖先,用a[i][0]表示第i个集合与祖先同类的人数,用a[i][1]表示第i个集合与祖先异类的人数。之后就是dp部分,dp[i][j]表示前i个集合中天使个数为j的方法数,按背包模板来就行。当dp[tot][p1]==1时有解,否则输出“no"。若有解还需要输出编号,只需要从dptot][p1]往前回溯即可,因为要按升序,需要sort一下。至此这道题才算结束,但因为敲错了一个变量名,我找了一个小时bug,写代码时还是要心细,不然太折磨人了。

代码如下:

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; int n,p1,p2,x,y,d;
int root[],f[],dp[][],r[],a[][],res[]; int getr(int k){
if(root[k]==k) return k;
else{
int tmp=root[k];
root[k]=getr(root[k]);
f[k]^=f[tmp];
return root[k];
}
} int main(){
while(scanf("%d%d%d",&n,&p1,&p2),n||p1||p2){
for(int i=;i<=p1+p2;++i)
root[i]=i,f[i]=,a[i][]=a[i][]=;
while(n--){
char ch[];
scanf("%d%d%s",&x,&y,ch);
if(ch[]=='y') d=;
else d=;
int rx=getr(x),ry=getr(y);
if(rx!=ry){
root[ry]=rx;
f[ry]=f[x]^f[y]^d;
}
}
int tot=;
memset(dp,,sizeof(dp));
for(int i=;i<=p1+p2;++i){
if(i==getr(i)){
r[++tot]=i;
for(int j=;j<=p1+p2;++j)
if(getr(j)==i)
if(f[j]==) a[tot][]++;
else a[tot][]++;
}
}
dp[][]=;
for(int i=;i<=tot;++i){
for(int j=p1;j>=a[i][];--j)
dp[i][j]+=dp[i-][j-a[i][]];
for(int j=p1;j>=a[i][];--j)
dp[i][j]+=dp[i-][j-a[i][]];
}
if(dp[tot][p1]!=){
printf("no\n");
continue;
}
int p=p1,num=;
for(int i=tot;i>=;--i)
if(dp[i-][p-a[i][]]==){
for(int j=;j<=p1+p2;++j)
if(getr(j)==r[i]&&f[j]==)
res[num++]=j;
p-=a[i][];
}
else{
for(int j=;j<=p1+p2;++j)
if(getr(j)==r[i]&&f[j]==)
res[num++]=j;
p-=a[i][];
}
sort(res,res+num);
for(int i=;i<num;++i)
printf("%d\n",res[i]);
printf("end\n");
}
return ;
}

poj1417(带权并查集+背包DP+路径回溯)的更多相关文章

  1. poj1417 带权并查集 + 背包 + 记录路径

    True Liars Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 2713   Accepted: 868 Descrip ...

  2. poj1417 带权并查集+0/1背包

    题意:有一个岛上住着一些神和魔,并且已知神和魔的数量,现在已知神总是说真话,魔总是说假话,有 n 个询问,问某个神或魔(身份未知),问题是问某个是神还是魔,根据他们的回答,问是否能够确定哪些是神哪些是 ...

  3. 西安邀请赛-D(带权并查集+背包)

    题目链接:https://nanti.jisuanke.com/t/39271 题意:给定n个物品,m组限制,每个物品有个伤害值,现在让两个人取完所有物品,要使得两个人取得物品伤害值之和最接近,输出伤 ...

  4. 洛谷P1196 [NOI2002]银河英雄传说(带权并查集)

    题目描述 公元五八○一年,地球居民迁至金牛座α第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争.泰山压顶 ...

  5. 【11.1校内测试】【快速幂DP】【带权并查集】【模拟】

    Solution $jzy$大佬用了给的原根的信息,加上矩阵快速幂150行QAQ 然而$yuli$大佬的做法不仅好懂,代码只有50行! 快速幂的思想,把m看成要组成的区间总长度,每次将两段组合得到新的 ...

  6. [NOIP摸你赛]Hzwer的陨石(带权并查集)

    题目描述: 经过不懈的努力,Hzwer召唤了很多陨石.已知Hzwer的地图上共有n个区域,且一开始的时候第i个陨石掉在了第i个区域.有电力喷射背包的ndsf很自豪,他认为搬陨石很容易,所以他将一些区域 ...

  7. luogu 2294 狡猾的商人 带权并查集

    此题做法多啊 带权并查集,区间dp,前缀和,差分约束 1.自己写的前缀和, 11 #include<bits/stdc++.h> #define rep(i,x,y) for(regist ...

  8. POJ 1733 Parity game (带权并查集)

    题意:有序列A[1..N],其元素值为0或1.有M条信息,每条信息表示区间[L,R]中1的个数为偶数或奇数个,但是可能有错误的信息.求最多满足前多少条信息. 分析:区间统计的带权并查集,只是本题中路径 ...

  9. POJ1984:Navigation Nightmare(带权并查集)

    Navigation Nightmare Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 7871   Accepted: 2 ...

随机推荐

  1. centos1.7 配置nginx+php+mysql客户端+thinkphp的rewrite实现

    1   . 安装php7     下载地址:https://secure.php.net/downloads.php这里下载的是:wget http://ar2.php.net/distributio ...

  2. HUD 1175 连连看

    连连看 Time Limit : 20000/10000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submiss ...

  3. http 各个状态返回值

    code 定义在 org.apache.http.HttpStatus 转载来自于:http://desert3.iteye.com/blog/1136548 502 Bad Gateway:tomc ...

  4. 廖雪峰Java1-1Java入门-java简介

    Java特点: 一种面向对象的跨平台变成语言 以字节码方式运行在虚拟机上 自带功能齐全的类库 非常活跃的开源社区支持 Java优点: 简单.健壮.安全 跨平台,一次编写,到处运行 高度优化的虚拟机 J ...

  5. PHP mysqli_free_result()与mysqli_fetch_array()函数

    mysql_free_result() 仅需要在考虑到返回很大的结果集时会占用多少内存时调用.在脚本结束后所有关联的内存都会被自动释放. 在我们执行完SELECT语句后,释放游标内存是一个很好的习惯. ...

  6. css常用字体

    宋体 SimSun 黑体 SimHei 微软雅黑 Microsoft YaHei 微软正黑体 Microsoft JhengHei 新宋体 NSimSun 新细明体 PMingLiU 细明体 Ming ...

  7. 使用promise对象封装一个ajaxGet函数

    function promiseAjax(url,data){        var pro = new Promise(function(success,failed){           承诺一 ...

  8. js实现复选框的全选和全不选

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  9. thinkphp5隐藏apache下的index.php

    在应用入口文件同级目录添加.htaccess文件,内容如下: <IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews Re ...

  10. forward与redirect的区别

    1.从地址栏显示来说forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址 ...