poj 1182   http://poj.org/problem?id=1182

分析:这个题大意说的非常清楚了,就是求出假话的个数,题目中给的假话要求有三个

① 当前的话与前面的某些真的话冲突,是假话;

②当前的话中X或Y比N大,是假话;

③当前的话表示X吃X,是假话。

②和③很好判断了,最难的就是假话条件①啦!!    题中说有三种动物A,B,C;   A-->B-->C-->A(A吃B, B吃C,C又吃A), 形成一个环; 然而我们又没办法把所给的动物(数字代替)确切的分给哪一类。 那么就不分了,既然这三种动物构成一个环么,那么我们就将所有相关联的元素合并成一个集合。 集合中有一个代表元素(下面也可能叫根元素)。 通过元素与根元素的关系  来区别他们。 relation[i] = 0 表示与根元素同类relation[i] = 1 表示吃根元素的那类, relation[i] = 2 表示被根元素吃的一类。 通过元素与根元素的关系清晰的将他们分为三类,又不用确切表明哪一类。

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std; int n, m, d, x, y, fx, fy, sum, pre[], relation[];
//初始化集合
void init()
{
for(int i = ; i <= n; i++)
{
pre[i] = i;
relation[i] = ;
}
}
int find(int a)//寻找最终代表元素
{
int i, j;
i = a;
if(pre[a] == a)
return a;
else
{
j = pre[i];
pre[i] = find(j);//通过递归方式
relation[i] = (relation[i] + relation[j]) % ;
//这个地方关键。 边寻找根元素, 边得出和根元素的关系。 这通过
//该元素和父亲元素的关系 还有 父亲元素和根元素的关系 求出。
//这个关系式我是枚举后 总结的 下面有推出的过程。
}
return pre[a];
}
//在这我写了两个合并的函数Union1,Union2,主要是因为d = 1时和 d = 2时
//求relation的方程不同,这个方程在下面也有推到过程
void Union1(int a, int b)
{
pre[fx] = fy;
relation[fx] = ( + (relation[b] - relation[a])) % ;
}
void Union2(int a, int b)
{
pre[fx] = fy;
relation[fx] = ( + (relation[b] - relation[a]) + ) % ;
} int main()
{
scanf("%d%d", &n, &m);
init();
sum = ;
for(int i = ; i <= m; i++)
{
scanf("%d%d%d", &d, &x, &y);
if(x > n || y > n || (d == && x == y))
{
sum++;
continue;
}
fx = find(x);
fy = find(y);
//若x和y的根元素不同,就代表至少其中一个元素不再集合里,需要合并元素
if(fx != fy)
{
if(d == )
Union1(x, y);
else
Union2(x, y);
}
//当x和y的根元素相同时,就代表他们都是集合里的啦! 这使得工作就关键啦!!
//需要判断这是给的关系和原本存在的关系是否冲突, 如果冲突, 假话就得多一个咯!
else if(fx == fy)
{
if(d == )
{
if(relation[x] != relation[y])
sum++;
}
if(d == )
{
if(relation[x] != (relation[y]+) % )
sum++;
}
}
}
printf("%d\n", sum);
return ;
}

Union2  relation[fx] = (3 + (relation[b] - relation[a]) + 1) % 3;

x与根元素fx的关系 y与根元素fy的关系 fx与fy的关系 relation[b] - relation[a]
0                          0 1 0
1 0 0 -1
2 0 2 -2
0 1 2 1
1 1 1 0
2 1 0 -1
0 2 0 2
1 2 2 1
2 2 1 0

Union1      relation[fx] = (3 + (relation[b] - relation[a])) % 3;

x与根元素fx的关系 y与根元素fy的关系 fx与fy的关系 relation[b] - relation[a]
0 0 0 0
0 1 1 1
0 2 2 2
1 0 2 -1
1 1 0 0
1 2 1 1
2 0 1 -2
2 1 2 -1
2 2 0 0

find   relation[i] = (relation[i] + relation[j]) % 3;

i元素与父亲元素j的关系 j元素与根元素的关系 i元素与根元素的关系
0 0 0
0 1 1
0 2 2
1 0 1
1 1 2
1 2 0
2 0 2
2 1 0
2 2 1

poj2492 和这个题类似 , 他只是将A,B,C三类动物 变成 男,女两种类。relation可能是同类或异类。如果出现一对是同类那么说明 有异常。 relation关系式:   find寻找时relation[i] = (relation[i] + relation[j]) % 2;    合并时relation[fx] = (relation[a] + relation[b] + 1) % 2。

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std; int n, m, x, y, flag, pre[], relation[];
void init()
{
for(int i = ; i <= n; i++)
{
pre[i] = ;
relation[i] = ;
}
}
int find(int a)
{
int r, i, j;
r = a; i = a;
if(pre[a] == a)
return a;
else
{
j = pre[i];
pre[i] = find(j);
relation[i] = (relation[i] + relation[j]) % ;
}
return pre[a];
}
void Union(int a, int b)
{
int fx = find(a);
int fy = find(b);
if(fx != fy)
pre[fx] = fy;
relation[fx] = (relation[a] + relation[b] + ) % ;
}
int main()
{
int t, num; cin >> t;
num = ;
while(num < t)
{
scanf("%d%d", &n, &m);
init();
flag = ;
for(int i = ; i <= m; i++)
{
scanf("%d%d", &x, &y);
if(flag == )continue;
int fx = find(x);
int fy = find(y);
if(fx != fy)
Union(x, y);
else if(fx == fy)
{
if(relation[x] == relation[y])
{
flag = ;
printf("rela%d == rela%d\n", x, y);
}
}
}
printf("Scenario #%d:\n", ++num);
if(flag == )
printf("Suspicious bugs found!\n\n");
else if(flag == )
printf("No suspicious bugs found!\n\n");
}
return ;
}

poj1182 食物链(种类并查集)详解的更多相关文章

  1. NOI2001|POJ1182食物链[种类并查集 向量]

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 65430   Accepted: 19283 Description ...

  2. POJ1182 食物链 —— 种类并查集

    题目链接:http://poj.org/problem?id=1182 食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: ...

  3. poj1182(种类并查集好题)

    不得不说,我得感谢@驱动幽灵百鬼夜行小肆,正是因为看明白了他给出的解析,我才完全弄懂种类并查集的,这里,我也不想去改其他的,就直接引用他的解题报告吧 转载:http://blog.csdn.net/c ...

  4. POJ1182 食物链(并查集)

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 55260   Accepted: 16210 Description ...

  5. POJ1182食物链(并查集)

    Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到 ...

  6. POJ-1182 食物链(并查集)

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 75814   Accepted: 22528 Description ...

  7. poj1182 食物链【并查集-好题!】

    动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A.  现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两 ...

  8. - > 并查集详解(第二节)

    以下是并查集思路详解: 一:概念 并查集处理的是“集合"之间的关系.当给出两个元素的一个无序数对(a,b)时,需要快速“合并”a和b分别所在的集合,这期间需要反复“查找”某元素所在的集合.“ ...

  9. POJ1182食物链 (并查集)

    第一反应就是和那个搞基的虫子的题很像(poj2492 http://www.cnblogs.com/wenruo/p/4658874.html),不过是把种类从2变成了3. 错在很白痴的地方,卡了好久 ...

  10. poj1182 食物链(并查集 好题)

    https://vjudge.net/problem/POJ-1182 并查集经典题 对于每只动物创建3个元素,x, x+N, x+2*N(分别表示x属于A类,B类和C类). 把两个元素放在一个组代表 ...

随机推荐

  1. Setting Up the ADT Bundle

    Setting Up the ADT Bundle The ADT Bundle provides everything you need to start developing apps, incl ...

  2. Maven之debug技巧

    mvn eclipse:clean eclipse:eclipse -Dwtpversion=2.0 可以将项目编译为web项目,然后再项目上右键debug as server即可.

  3. mysql server install

    1.首先在mysql的官网www.mysql.com或者其他网站下载mysql.zip或者mis格式的文件目前5.6的差不多300多M. 2.zip压缩包是绿色版的不用安装,直接用dos命令操作就行. ...

  4. 各种sensor名称统计

    gyroscopes 陀螺仪accelerometers 加速度计magnetometers 磁力计barometric pressure 气压remote pressure sensing 远程压力 ...

  5. ubuntu14.04安装opencv3.0

    sudo apt-get update sudo apt-get upgrade 搭建C/C++编译环境: sudo apt-get install build-essential 安装关联库: su ...

  6. Nyoj42 一笔画问题 (欧拉道路)

    http://acm.nyist.net/JudgeOnline/problem.php?pid=42题目链接 #include <cstdio> #include <cstring ...

  7. 扫描线专题 hdu1255

    hdu1255 求覆盖至少两次的面积,和直接求覆盖面积比,就是保证cover>1就可以了. 没有进行lazy操作,因为每一次更新伴随着询问,感觉没有必要.982MS水过. #include &l ...

  8. 洛谷P1471 方差

    蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数.他想算算这个数列的平均数和方差. ——by 洛谷; http://www.luogu.org/problem/show?pid=1 ...

  9. git 删除分支和删除文件夹

    1.删除分支 1.1查看所有分支: git branch -a 得到结果: 1.2删除HEAD分支 git push origin --delete HEAD 2.删除文件夹 2.1 查看本地分支下的 ...

  10. windows批量创建用户

    一.建立用户的命令行语法: 建立用户:net  user  用户名  密码  /add           (如:net user test 123 /add)  提升权限:net  localgro ...