poj 1417(并查集+简单dp)
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 2087 | Accepted: 640 |
Description
which he had heard from patriarchs in his childhood. This must be the island in the legend. In the legend, two tribes have inhabited the island, one is divine and the other is devilish, once members of the divine tribe bless you, your future is bright and
promising, and your soul will eventually go to Heaven, in contrast, once members of the devilish tribe curse you, your future is bleak and hopeless, and your soul will eventually fall down to Hell.
In order to prevent the worst-case scenario, Akira should distinguish the devilish from the divine. But how? They looked exactly alike and he could not distinguish one from the other solely by their appearances. He still had his last hope, however. The members
of the divine tribe are truth-tellers, that is, they always tell the truth and those of the devilish tribe are liars, that is, they always tell a lie.
He asked some of them whether or not some are divine. They knew one another very much and always responded to him "faithfully" according to their individual natures (i.e., they always tell the truth or always a lie). He did not dare to ask any other forms of
questions, since the legend says that a devilish member would curse a person forever when he did not like the question. He had another piece of useful informationf the legend tells the populations of both tribes. These numbers in the legend are trustworthy
since everyone living on this island is immortal and none have ever been born at least these millennia.
You are a good computer programmer and so requested to help Akira by writing a program that classifies the inhabitants according to their answers to his inquiries.
Input
n p1 p2
xl yl a1
x2 y2 a2
...
xi yi ai
...
xn yn an
The first line has three non-negative integers n, p1, and p2. n is the number of questions Akira asked. pl and p2 are the populations of the divine and devilish tribes, respectively, in the legend. Each of the following n lines has two integers xi, yi and one
word ai. xi and yi are the identification numbers of inhabitants, each of which is between 1 and p1 + p2, inclusive. ai is either yes, if the inhabitant xi said that the inhabitant yi was a member of the divine tribe, or no, otherwise. Note that xi and yi
can be the same number since "are you a member of the divine tribe?" is a valid question. Note also that two lines may have the same x's and y's since Akira was very upset and might have asked the same question to the same one more than once.
You may assume that n is less than 1000 and that p1 and p2 are less than 300. A line with three zeros, i.e., 0 0 0, represents the end of the input. You can assume that each data set is consistent and no contradictory answers are included.
Output
end in a line. Otherwise, i.e., if a given data set does not include sufficient information to identify all the divine members, print no in a line.
Sample Input
2 1 1
1 2 no
2 1 no
3 2 1
1 1 yes
2 2 yes
3 3 yes
2 2 1
1 2 yes
2 3 no
5 4 3
1 2 yes
1 3 no
4 5 yes
5 6 yes
6 7 no
0 0 0
Sample Output
no
no
1
2
end
3
4
5
6
end
题意:有A和B两个部落,A部落的人都是好人,始终讲实话,而B部落的人都是坏淫,都说谎话,题目给出n,代表问题的个数,给出p1和p2代表两个部落的人,然后a,b,ch,如果a说b是好人则ch是yes,否则是no,然后根据问题得出的回答能不能确定谁是好人,谁是坏淫,若可以且情况唯一,则按顺序输出好人的编号,否则输出no
分析:对于a,b,yes,若a是好人,则b一定是好人,若a是坏淫,则b一定是坏人,对于a,b,no,若a是好人,则b是坏人,若a是坏人,则a在说谎,b则是好人,所以yes的时候a和b在同一个集合中,no的时候a和b不在一个集合中,所以,应该用并查集路径压缩判断,得出每个集合的两类人数,然后利用dp[i][j]记录到第i个集合的时候有j个好人的情况个数,若为一种情况,则用pre[i][j]记录路径
程序:
#include"cstdio"
#include"cstring"
#include"cstdlib"
#include"cmath"
#include"string"
#include"map"
#include"cstring"
#include"iostream"
#include"algorithm"
#include"queue"
#include"stack"
#define inf 0x3f3f3f3f
#define M 1000
#define eps 1e-8
#define INT int
using namespace std;
int f[M],h[M],num[M],sum[M],pre[M][M],s[M];
int dp[M][M];
struct node
{
int a,b;
}belong[M],mark[M];
int finde(int x)
{
if(x!=f[x])
{
int y=f[x];
f[x]=finde(f[x]);
sum[x]=(sum[x]+sum[y])%2;
}
return f[x];
}
void make(int a,int b,int k)
{
int x=finde(a);
int y=finde(b);
if(x<y)
{
f[y]=x;
sum[y]=(2+sum[y]+sum[a]+k-sum[b])%2;
h[x]+=h[y];
}
else if(y<x)
{
f[x]=y;
sum[x]=(2+sum[x]+sum[b]+k-sum[a])%2;
h[y]+=h[x];
}
}
int main()
{
int n,p1,p2;
while(scanf("%d%d%d",&n,&p1,&p2),n||p1||p2)
{
memset(belong,0,sizeof(belong));
memset(mark,0,sizeof(mark));
for(int i=1;i<=p1+p2;i++)
{
f[i]=i;
h[i]=1;
sum[i]=0;
}
for(int i=1;i<=n;i++)
{
int a,b;
char ch[6];
scanf("%d%d%s",&a,&b,ch);
if(strcmp(ch,"yes")==0)
make(a,b,0);
else
make(a,b,1);
}
int cnt=0;
for(int i=1;i<=p1+p2;i++)
{
if(f[i]==i)
{
num[i]=++cnt;
}
}
for(int i=1;i<=p1+p2;i++)
{
f[i]=finde(i);
if(sum[i]==0)
belong[num[f[i]]].a++;
else
belong[num[f[i]]].b++;
}
//for(int i=1;i<=cnt;i++)
//printf("%d %d\n",belong[i].a,belong[i].b);
memset(dp,0,sizeof(dp));
memset(pre,-1,sizeof(pre));
dp[0][0]=1;
for(int i=1;i<=cnt;i++)
{
for(int j=p1;j>=0;j--)
{
if(j-belong[i].a>=0)
dp[i][j]+=dp[i-1][j-belong[i].a];
if(j-belong[i].b>=0)
dp[i][j]+=dp[i-1][j-belong[i].b]; if(dp[i][j]==1)
{
if(j-belong[i].a>=0&&dp[i-1][j-belong[i].a]==1)
{
pre[i][j]=1;
}
if(j-belong[i].b>=0&&dp[i-1][j-belong[i].b]==1)
{
pre[i][j]=2;
}
}
}
}
if(dp[cnt][p1]!=1)
{
printf("no\n");
}
else
{
int j=p1;
for(int i=cnt;i>=1;i--)
{
if(pre[i][j]==1)
{
//printf("%d\n",belong[i].a);
j-=belong[i].a;
mark[i].a++;
}
else
{
//printf("%d\n",belong[i].b);
j-=belong[i].b;
mark[i].b++;
}
}
int cot=0;
for(int i=1;i<=p1+p2;i++)
{
if(mark[num[f[i]]].a&&sum[i]==0)
{
s[cot++]=i;
}
else if(mark[num[f[i]]].b&&sum[i]==1)
{
s[cot++]=i;
}
}
for(int i=0;i<cot;i++)
printf("%d\n",s[i]);
printf("end\n");
}
}
return 0;
}
poj 1417(并查集+简单dp)的更多相关文章
- POJ 1417 并查集 dp
After having drifted about in a small boat for a couple of days, Akira Crusoe Maeda was finally cast ...
- POJ - 1417 并查集+背包
思路:很简单的种类并查集,利用并查集可以将所有的人分成几个集合,每个集合又分为好人和坏人集合,直接进行背包dp判断有多少种方法可以在取了所有集合并且人数正好凑足p1个好人的方案.dp(i, j)表示前 ...
- hdu 4514 并查集+树形dp
湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Tot ...
- poj 1984 并查集
题目意思是一个图中,只有上下左右四个方向的边.给出这样的一些边, 求任意指定的2个节点之间的距离. 就是看不懂,怎么破 /* POJ 1984 并查集 */ #include <stdio.h& ...
- C - BLG POJ - 1417 种类并查集加dp(背包)
思路:刚看这道题感觉什么都不清楚,人物之间的关系一点也看不出来,都不知道怎么写,连并查集都没看出来,但是你可以仔细分析一下,当输入字符串为“yes”的时候,我们设输入的值为x和y,当x为天使是则由题可 ...
- poj1417(带权并查集+背包DP+路径回溯)
题目链接:http://poj.org/problem;jsessionid=8C1721AF1C7E94E125535692CDB6216C?id=1417 题意:有p1个天使,p2个恶魔,天使只说 ...
- poj1611(并查集简单应用)
题目链接:http://poj.org/problem?id=1611 思路: 显然是一个并查集的题,很简单,只要将一个group中的学生并在一起,最后遍历1到n-1,看有多少学生的祖先与0的祖先相等 ...
- poj 1733 并查集+hashmap
题意:题目:有一个长度 已知的01串,给出多个条件,[l,r]这个区间中1的个数是奇数还是偶数,问前几个是正确的,没有矛盾 链接:点我 解题思路:hash离散化+并查集 首先我们不考虑离散化:s[x] ...
- HDU 5575 Discover Water Tank 并查集 树形DP
题意: 有一个水槽,边界的两块板是无穷高的,中间有n-1块隔板(有高度),现有一些条件(i,y,k),表示从左到右数的第i列中,在高度为(y+0.5)的地方是否有水(有水:k = 1),问最多能同时满 ...
随机推荐
- regardless of how many processors are devoted to a parallelized execution of this program
https://en.wikipedia.org/wiki/Amdah's_law Amdahl's law is often used in parallel computing to predic ...
- Delphi Application.MessageBox详解
引数:1. Text:要显示的讯息2. Caption:讯息视窗的标题列文字3. Flags:讯息旗标 3.1. 可指定讯息视窗上的图示 3.2. 可指定讯息视窗出现的按钮 3 ...
- Grid组件 列头居中
在grdMain组件中的 class中设置“ x-grid-title-center ”
- filter:Alpha总结
filter:Alpha(Opacity=?, FinishOpacity=?, Style=?, StartX=?, StartY=?, FinishX=?, FinishY=?)Opacity:透 ...
- windbg sos版本不匹配问题解决
dumpheap 时提示: 0:105> !dumpheap -stat The garbage collector data structures are not in a valid sta ...
- Google物联网操作系统协同框架Weave深度解析
1. Google Weave框架 在2015年的Google I/O大会上,负责Android业务的桑达.皮查伊(SundarPichai)宣布了Google最新的物联网战略.这包括一个 ...
- 详解 Qt 线程间共享数据(用信号槽方式)
使用共享内存.即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的. Qt 线程间共享数据是本文介绍的内容,多的不说,先来啃内容.Qt线程间共享 ...
- angularJS推荐显示注入写法
使用js压缩工具时发现压缩之后的控制器注入参数由原来的$scope变成了a,b...这样的字母而导致js失效,那么我们推荐使用完整的显示注入方式来解决此问题! //隐式注入的写法 angular.mo ...
- 设计模式:桥连模式(Bridge)
定 义:将抽象部分和它的实现部分分离,使它们可以独立的变化. 结构图: 实现类: //Implementor(实现)类 public abstract class Implementor { pu ...
- Provisioning Profile
什么是Provisioning Profile? 从字面翻译,Provisioning Profile就是配置文件的意思,它在开发者账号体系中所扮演的角色也是配置和验证的作用.如果你有开发者账号,可以 ...