题目链接: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. 杂项:SQLite

    ylbtech-杂项:SQLite SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中.它是D.RichardHipp建立的公有领域项目.它的设计目标是 ...

  2. Oracle 同一个字段的两值进行加减计算

    如 病人ID      入院日期                出院日期 00001      2016-09-01          2016-09-10 00001      2016-09-15 ...

  3. javascript的面向对象思想知识要点

    获取数据类型 typeof undefined:访问某个不存在的或未经赋值的变量时就会得到一个 undefined,用typeof 获取类型,得到的也是undefined;null:它不能通过java ...

  4. 第14章 UDP编程(1)_UDP客户端服务器模型

    1. UDP编程模型 (1)UDP客户端服务器模型 ①客户端可以不调用bind()而直接与服务器通讯. ②UDP是无连接的,因此服务端不需要调用accept和listen,客户端也无需调用connec ...

  5. 使用SolrNet访问Solr-5.5.0

    由于今年年初刚发布的Solr-5.5.0,网上所能找到的资料少之又少,所以只能靠自己一点点摸索. 从某Hub上下载了SolrNet源码,按照教程提交文档或者查询均失败,无奈只得跟断点一点点差怎么回事. ...

  6. Angular4之常用指令

    Angular4指令 NgIf <div *ngIf="false"></div> <!-- never displayed --> <d ...

  7. webpack(2)--Entry

    Entry entry是配置模块的入口,可以抽象成输入,webpack执行构建的第一步将从入口开始搜寻及递归解析出所有入口依赖的模块. 注意: entry是必填,若不填写则将导致webpack报错退出 ...

  8. Selenium 错误处理之:stale element reference: element is not attached to the page document

    出现该错误的原因是页面在获取到DOM元素之后到引用元素之间页面进行了刷新,所以需要再次获取该DOM元素即可.

  9. CSS3基础

    内容: 1.圆角 border-radius 2.阴影 text-shadow.box-shadow 3.渐变 linear.radial 4.rgba rgb+alpha opacity 5.tra ...

  10. 20180130之PYTHON学习笔记【PYTHON3写个自动听课功能】

    -----------------------原始实现想法------------ import pyautoguifrom PIL import Image#img=Image.open('c:/p ...