poj1417 True Liars[并查集+背包]
有一点小转化的题,在设计dp状态时还是有点费脑筋的。
地址。
依题意,首先可以知道肯定要扩展域的并查集(明摆着的嘛)。一个"好人"域,一个"坏人"域,每句话分两种情况考虑连边。假设是yes,同域连边,否则异域连边(经典模型嘛)。然后就是要考虑如何验证是否有$x$个好人$y$个坏人的唯一解存在。这取决于联通块。
可以参考我瞎画的图,上面点1~N,下面点N+1~2N。

由于并查集合并时操作的对称性,可以发现一个联通块要么$x$个好人$y$个坏人要么$y$个好人$x$个坏人。那么对于所有联通块必须选其中一种方案,最后要凑齐。于是我就想到二维的背包。。但是复杂度太大了啊。。卡了好久,于是又手玩了样例。发现当我所有联通块恰好凑出x个好人时,剩下的不就全是坏人吗。所以只要去做一个好人的背包就行了。dp的时候由于没处理好关于多解的问题,又调了半小时。。一题做两个小时我也是醉了。。其实就是有前面一个状态转移,记一下$pre$。在记一下方案。最终好人的背包装满的状态方案不是1种就是无解,是一种就把所有好人找出来,这个我开了vector存了每个联通块。细节还看code,虽然可能写繁掉了qwq。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#define dbg(x) cerr<<#x<<" = "<<x<<endl
#define ddbg(x,y) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<endl
using namespace std;
typedef long long ll;
template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=+;
int fa[N<<],f[N][N>>],cnt[N][N>>],pos[N],tot,tot2,ans[N];
vector<int> a[N],b[N];
int n,m,gd,bd,x,y;
inline int Get(int x){return fa[x]^x?fa[x]=Get(fa[x]):x;} int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
while(read(m),read(gd),read(bd),m||gd||bd){
n=gd+bd;char s[];tot=,tot2=;memset(pos,,sizeof pos);
for(register int i=;i<=n;++i)a[i].clear(),b[i].clear();
for(register int i=;i<=(n<<);++i)fa[i]=i;
for(register int i=;i<=m;++i){
read(x),read(y),scanf("%s",s);
if(x==y)continue;
if(s[]=='y')fa[Get(x)]=Get(y),fa[Get(x+n)]=Get(y+n);
else fa[Get(x)]=Get(y+n),fa[Get(x+n)]=Get(y);
}
for(register int i=;i<=n;++i)if(Get(i)<=n)a[Get(i)].push_back(i);
for(register int i=n+;i<=(n<<);++i)if(Get(i)<=n)b[Get(i)].push_back(i-n);
for(register int i=;i<=n;++i)if(!a[i].empty()||!b[i].empty())pos[++tot]=i;//联通块统计
memset(f,,sizeof f);memset(cnt,,sizeof cnt);cnt[][]=;
for(register int i=;i<=tot;++i){
x=a[pos[i]].size(),y=b[pos[i]].size();
for(register int j=,lx=j-x,ly=j-y;j<=gd;++j,lx=j-x,ly=j-y){
if(lx<&&ly>=)f[i][j]=ly,cnt[i][j]=cnt[i-][ly];
else if(lx>=&&ly<)f[i][j]=lx,cnt[i][j]=cnt[i-][lx];
else if(lx>=&&ly>=)f[i][j]=cnt[i-][lx]?lx:ly,cnt[i][j]=cnt[i-][lx]+cnt[i-][ly];
}
}//做dp
if(cnt[tot][gd]^)printf("no\n");
else{
int j=gd;
while(tot){
if(j-f[tot][j]==a[pos[tot]].size()){for(register int i=;i<a[pos[tot]].size();++i)ans[++tot2]=a[pos[tot]][i];}
else for(register int i=;i<b[pos[tot]].size();++i)ans[++tot2]=b[pos[tot]][i];
j=f[tot--][j];
}//推回去
sort(ans+,ans+tot2+);
for(register int i=;i<=tot2;++i)printf("%d\n",ans[i]);
printf("end\n");
}
}
return ;
}
poj1417 True Liars[并查集+背包]的更多相关文章
- POJ1417 True Liars 并查集 动态规划 (种类并查集)
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ1417 题意概括 有一群人,p1个好人,p2个坏人. 他们说了n句话.(p1+p2<=600,n ...
- POJ1417 True Liars —— 并查集 + DP
题目链接:http://poj.org/problem?id=1417 True Liars Time Limit: 1000MS Memory Limit: 10000K Total Submi ...
- 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个恶魔,天使只说 ...
- POJ1417:True Liars(DP+带权并查集)
True Liars Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- poj1417 true liars(并查集 + DP)详解
这个题做了两天了.首先用并查集分类是明白的, 不过判断是否情况唯一刚开始用的是搜索.总是超时. 后来看别人的结题报告, 才恍然大悟判断唯一得用DP. 题目大意: 一共有p1+p2个人,分成两组,一组p ...
- poj1417 带权并查集+0/1背包
题意:有一个岛上住着一些神和魔,并且已知神和魔的数量,现在已知神总是说真话,魔总是说假话,有 n 个询问,问某个神或魔(身份未知),问题是问某个是神还是魔,根据他们的回答,问是否能够确定哪些是神哪些是 ...
- POJ1417 True Liars
题意 Language:Default True Liars Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6392 Accep ...
- POJ - 1417 并查集+背包
思路:很简单的种类并查集,利用并查集可以将所有的人分成几个集合,每个集合又分为好人和坏人集合,直接进行背包dp判断有多少种方法可以在取了所有集合并且人数正好凑足p1个好人的方案.dp(i, j)表示前 ...
随机推荐
- GitHub上编程语言流行度分析
GitHub已然是全球最流行的开源项目托管平台,项目数量眼下已经达到了千万级别.Adereth在Counting Stars on GitHub一文提供了一个很有意思的思路,那就是籍GitHub用户通 ...
- JOB Hunting 总结-----2013-11-5
从9月份开始的找工作大战,告一段落:其实早在10月中旬就已搞定,现在回想起这过去的几个月,很充实,很疲惫,很挫败又很有成就感! 开始找工作,对未来有过很多憧憬,也很迷茫,不知道自己的未来会在 ...
- Android----SharedPreferences(存储数据)
SharedPreferences详解 我们在开发软件的时候,常需要向用户提供软件参数设置功能,例如我们常用的微信,用户可以设置是否允许陌生人添加自己为好友.对于软件配置参数的保存,如果是在windo ...
- erlang进程监控:link和monitor
Erlang最开始是为了电信产品而发展起来的语言,因为这样的目的,决定了她对错误处理的严格要求.Erlang除了提供exception,try catch等语法,还支持Link和Monitor两种监控 ...
- MySQL -- Ubuntu下的操作命令
=======================安装======================参照MySQL官网的步骤:https://dev.mysql.com/doc/mysql-apt-repo ...
- windowsphone8.1学习笔记之应用数据(一)
数据存储分为两种:云存储和应用数据(即本地存储),wp中的应用数据分为两种,一种是应用设置:一种是应用文件.wp的数据相关都是通过ApplicationData来实现,一个程序只有数据存储区. 先说应 ...
- 九度OJ 1063:整数和 (基础题)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3456 解决:2254 题目描述: 编写程序,读入一个整数N. 若N为非负数,则计算N到2N之间的整数和: 若N为一个负数,则求2N到N之间 ...
- restlet验证
1 restlet有无认证对比 无认证: 客户端发起请求 -----> 服务器路由 -----> 访问服务端资源 有认证: 客户端发起请求 -----> 认证 ----->服务 ...
- 在tomcat下直接访问Html报错,说找不到资源(404)
今天由于工作需要,想把一个html直接放到tomcat(干净的tomcat,没有做过任何修改.)下进行访问,然后根据经验就直接在webapps下创建了个文件夹test,然后把需要的test.html拷 ...
- js作用域总结
一.在ES5中,js 的作用域 js作用域,只有全局作用域与函数作用域,没有块级作用域. 1.全局作用域 var a = 10; function aaa() {alert(a) } function ...