POJ1417 True Liars 题解
通过读题,容易发现,当回答为yes
时 \(x,y\) 必属于同类,当回答为no
时二者必为异类(并且当 \(x=y\) 时,回答必为yes
,不过这题不用这个性质)。
于是先按关系维护连通块,然后求出每个连通块的人数,用背包看是否能够凑出。可以把一个连通块的看作一个物品,总共的天神数就是背包的容量。
还用了set
辅助维护每个连通块里具体是哪些人。
这道题刚开始一直卡着,结果照着样例手玩一遍就全懂了,所以光空想还是不行的。
具体看丑陋的代码吧……
#include <bits/stdc++.h>
using namespace std;
const int N=1005,M=605;
struct path{int r1,r2,rd1,rd2;}p[M];
set<int> s[M<<1];
int fa[M<<1],n,m,p1,p2,d[M<<1],f[M][M];
int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
void merge(int x,int y) {fa[find(x)]=find(y);}
int main()
{
while(~scanf("%d%d%d",&n,&p1,&p2)&&(n||p1||p2))
{
m=p1+p2;
for(int i=1;i<=m+m;++i) fa[i]=i,s[i].clear();
for(int i=1,x,y;i<=n;++i)
{
char s[5];
scanf("%d %d %s",&x,&y,s);
if(s[0]=='y') merge(x,y),merge(x+m,y+m);
else merge(x,y+m),merge(x+m,y);
}
memset(d,0,sizeof(d));
for(int i=1;i<=m;++i)
{
int x=find(i);
d[x]++; s[x].insert(i);
}
int cnt=0;
for(int i=1;i<=m+m;++i)
{
if(!d[i]) continue;
int x=i<=m?i:i-m;int y=x+m;
x=find(x),y=find(y);
p[++cnt].r1=d[x];
p[cnt].r2=d[y];
p[cnt].rd1=x,p[cnt].rd2=y;
d[x]=d[y]=0;
}
memset(f,0,sizeof(f));
f[0][0]=1;
for(int i=1;i<=cnt;++i)
for(int j=p1;~j;--j)
{
if(j>=p[i].r1) f[i][j]+=f[i-1][j-p[i].r1];
if(j>=p[i].r2) f[i][j]+=f[i-1][j-p[i].r2];
}
if(f[cnt][p1]!=1) puts("no");
else
{
set<int> ans; int sum=p1;
for(int i=cnt;i;--i)
if(f[i-1][sum-p[i].r1])
ans.insert(s[p[i].rd1].begin(),s[p[i].rd1].end()),sum-=p[i].r1;
else ans.insert(s[p[i].rd2].begin(),s[p[i].rd2].end()),sum-=p[i].r2;
for(int i : ans) printf("%d\n",i);
puts("end");
}
}
return 0;
}
POJ1417 True Liars 题解的更多相关文章
- POJ1417 True Liars
题意 Language:Default True Liars Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6392 Accep ...
- 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
题目链接:http://poj.org/problem?id=1417 True Liars Time Limit: 1000MS Memory Limit: 10000K Total Submi ...
- POJ1417 True Liars 并查集 动态规划 (种类并查集)
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ1417 题意概括 有一群人,p1个好人,p2个坏人. 他们说了n句话.(p1+p2<=600,n ...
- poj1417 true liars(并查集 + DP)详解
这个题做了两天了.首先用并查集分类是明白的, 不过判断是否情况唯一刚开始用的是搜索.总是超时. 后来看别人的结题报告, 才恍然大悟判断唯一得用DP. 题目大意: 一共有p1+p2个人,分成两组,一组p ...
- poj1417 True Liars[并查集+背包]
有一点小转化的题,在设计dp状态时还是有点费脑筋的. 地址. 依题意,首先可以知道肯定要扩展域的并查集(明摆着的嘛).一个"好人"域,一个"坏人"域,每句话分两 ...
- True Liars POJ - 1417
True Liars After having drifted about in a small boat for a couple of days, Akira Crusoe Maeda was f ...
- 【POJ1417】【带标记并查集+DP】True Liars
Description After having drifted about in a small boat for a couple of days, Akira Crusoe Maeda was ...
- F - True Liars - poj1417(背包+并查集)
题意:有这么一群人,一群好人,和一群坏人,好人永远会说实话,坏人永远说假话,现在给你一组对话和好人与坏人的数目P1, P2. 数据里面的no是A说B是坏人, yes代表A说B是好人,就是这样,问题能不 ...
随机推荐
- 【NX二次开发】三点画圆,三角形外心,已知三点求圆心
已知P1.P2.P3,求点O 算法:三点不在一条直线上时,通过连接任意两点,作中垂线.任意两条中垂线的交点是圆心.
- 【NX二次开发】Block UI 整形
属性说明 常规 类型 描述 BlockID String 控件ID Enable Logical 是否可操作 Group Logical ...
- 【NX二次开发】Block UI 集列表
属性说明 属性 类型 描述 常规 BlockID String 控件ID Enable Logical 是否可操作 Group ...
- 【NX二次开发】获取边的类型 UF_MODL_ask_edge_type
源码 extern DllExport void ufsta(char *param, int *returnCode, int rlen) { UF_initialize(); int edge_t ...
- 【无线通信篇01 | Zstack协议栈】CC2530 Zigbee Zstack协议栈组网项目及详细讲解篇
演示视频:https://www.bilibili.com/video/BV1Ew411o7Fp 物联网无线通信技术,ZigBee无线传感网络 CC2530最大的特点就是一个拥有无线收发器(RF)的单 ...
- noip2012 总结
Vigenère 密码 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密码.Vigenère 密码的加密解密算法简单易用,且破译 ...
- 支持向量机(SVM)之硬阈值
支持向量机 ( support vector machine, SVM ) 是使用超平面来对给定的 p 维向量进行分类的非概率二元线性分类器. 一.超平面 ( hyperplane ) 在一个p维的输 ...
- 在element的table修改事件中修改数据,table的数据也会修改
大家在修改的时候有的会通过点击事件里面获取点击列表的值然后去赋值,但是row是Object对象类型,如果直接赋值的话,就变成了浅拷贝,复制的是地址,导致在表单中改变值的时候table中的数据也跟着改变 ...
- 解决 Golnag Gin框架跨域
package main import ( "github.com/gin-gonic/gin" "awesomeProject/app/app_routers" ...
- java变量及常量
变量 本质:就是代表一个"可操作的存储空间",空间位置是确定的,但是里面放置什么值不确定.我们可通过变量名来访问"对应的存储空间",从而操纵这个"存储 ...