博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ1182---食物链(带权并查集~技巧性超强的解法)
阅读量:4046 次
发布时间:2019-05-25

本文共 1560 字,大约阅读时间需要 5 分钟。

参考:《挑战程序设计竞赛》

这本大佬写的书上面的办法,并没有去刻意的去保存权,来回地更改权值,已达到修改捕食关系的目的。详解如下:

前面的输入的决定了后面的正确与否,前面的输入具有不确定性,这点是题目的要求:“ 当前的话与前面的某些真的话冲突,就是假话; ”

思路:
第一组假设是D为1的情况,也就是两个是同一类的情况,反正没说是这个同一类属于ABC中的哪一类,所以有三种可能,把这三种可能都压进去。怎么压呢?核心来了!
开辟一个3*N数组,1…N代表A类,N+1…2N代表B类,2N+1…3N代表C类。
1)第一种,x和y属于同一种类———合并x-A和y-A、x-B和y-B、x-C和y-C。

2)第二种,x吃y—————————合并x-A和y-B、x-B和y-C、x-C和y-A。

压入的时候,要先判断是否这句话为假话。假如说输入了第一种情况 x,y是否同一类,要判断x-A和y-B,X-A和y-C是否在集合里了,

为什不判断x-B和y-C,x-B和y-A; x-C和y-A,x-C和y-B?
因为压入的时候,就是按照三种可能压入的,所以只需判断一种情况就行了,另外两种不用判断。

#include
#include
#include
using namespace std;int s[150300];int Find(int x){ if (s[x] < 0)return x; else return s[x]= Find(s[x]);//路径压缩}void unite(int x, int y){ int rootx = Find(x); int rooty = Find(y); if (rootx != rooty) s[rootx] = rooty;}bool same(int x, int y){ return Find(x) == Find(y);}int main(){ int N, K, D, x, y, ans = 0; cin >> N >> K; fill(s+1, s+3*N+1, -1); while(K--) { scanf("%d%d%d", &D, &x, &y); if (x > N || y > N) { ans++; continue; } if (D == 1) { if (same(x, y + N) || same(x, y + 2 * N)) ans++; else { unite(x, y); unite(x + N, y + N); unite(x + 2 * N, y + 2 * N); } } else { if (same(x, y) || same(x, y+2*N)) ans++; else { unite(x, y + N); unite(x + N, y + 2 * N); unite(x + 2 * N, y); } } } cout << ans<

转载地址:http://dkyci.baihongyu.com/

你可能感兴趣的文章
linux kconfig配置
查看>>
linux不同模块completion通信
查看>>
linux printf获得时间戳
查看>>
C语言位扩展
查看>>
linux irqdebug
查看>>
git 常用命令
查看>>
linux位操作API
查看>>
uboot.lds文件分析
查看>>
uboot start.s文件分析
查看>>
没有路由器的情况下,开发板,虚拟机Ubuntu,win10主机,三者也可以ping通
查看>>
本地服务方式搭建etcd集群
查看>>
安装k8s Master高可用集群
查看>>
忽略图片透明区域的事件(Flex)
查看>>
忽略图片透明区域的事件(Flex)
查看>>
AS3 Flex基础知识100条
查看>>
Flex动态获取flash资源库文件
查看>>
flex4 中创建自定义弹出窗口
查看>>
01Java基础语法-16. while循环结构
查看>>
01Java基础语法-18. 各种循环语句的区别和应用场景
查看>>
01Java基础语法-19. 循环跳转控制语句
查看>>