088_食物链问题(并查集)
2015-12-31 06:56
447 查看
食物链问题:有N个动物,每个动物只能为A,B,C三种动物中的一种,已知 A吃B, B吃C, C吃A。
现在给出K条信息,每条信息值可能为以下两种中的一种:
1. x,y属于同一种动物;
2. x吃y。
要求找出这K 条信息中不正确的条数。 题源来自《挑战程序竞赛》第二版88页。
此题使用并查集来实现应该比较方便。
先初始化并查集,对于每一个动物x,创建三个元素:x,x+N,x+2N,分别代表x为动物 A, B, C。
对于每一号动物,根据其可能性,可以归到如下三个集合中:
1. x为A以及其捕食关系;如1号动物为A,2号动物也为A,(1,2浩动物属于同种) 3号动物为B(1号吃3号)
2. x为B以及其捕食关系;
3. x为C以及其捕食关系;
以上三个并查集的集合,对于某一个来说,要么集合内全部成立,要么集合内全部不成立。
对于某一条信息,根据如下方式来维护并查集:
1. 如果x和y是同种,那么合并x-A和y-A,x-B和y-B,x-C和y-C, 即 (x,y)合并到第一个集合,(x+N,y+N)合并到第二个集合,(x+2N,y+2N)合并到第三个集合;
2. 如果x吃y,那么合并x-A和y-B,x-B和y-C,x-C和y-A,即(x,y+N)合并到第一个集合,(x+N,y+2N)合并到第二个集合,(x+2N,y)合并到第三个集合;
如果某个集合内的元素关系不冲突,那么这个集合就是可行的一个食物链关系。 可以看到由于我们维护集合关系的轮换性,如果第一个集合可行,那么第二,第三个集合同样可 行。同样,如果对于某一条信息,x-A的情况下在第一个集合中冲突,必有x-B在第二个集合中冲突,x-C在第三个集合中冲突。
所以,检测冲突时只需检测x-A的情况。
那么,如何检测冲突呢?
1.如果遇到第一种关系,即x,y属于同种,那么冲突的话就是有x吃y或者y吃x。
只需考虑x-A的情况,即发生了y-B,y-C的情况,具体为:(x-A,y-B)存在第一集合(x吃y已经存在),(x-A,y-C)存在第三集合(y吃x 已经存在)
2.如果遇到第二种关系,即x吃y,那么冲突的情况就是y吃x后者x与y同种。
同样只需考虑x-A的情况,即发生了y-A,y-C的情况,具体为(x-A,y-A)存在第一集合(x,y同种已经存在), (x-A,y-C)存在第三集合(y吃x已经存在)
使用并查集的same方法就能做出以上判断。
现在给出K条信息,每条信息值可能为以下两种中的一种:
1. x,y属于同一种动物;
2. x吃y。
要求找出这K 条信息中不正确的条数。 题源来自《挑战程序竞赛》第二版88页。
此题使用并查集来实现应该比较方便。
先初始化并查集,对于每一个动物x,创建三个元素:x,x+N,x+2N,分别代表x为动物 A, B, C。
对于每一号动物,根据其可能性,可以归到如下三个集合中:
1. x为A以及其捕食关系;如1号动物为A,2号动物也为A,(1,2浩动物属于同种) 3号动物为B(1号吃3号)
2. x为B以及其捕食关系;
3. x为C以及其捕食关系;
以上三个并查集的集合,对于某一个来说,要么集合内全部成立,要么集合内全部不成立。
对于某一条信息,根据如下方式来维护并查集:
1. 如果x和y是同种,那么合并x-A和y-A,x-B和y-B,x-C和y-C, 即 (x,y)合并到第一个集合,(x+N,y+N)合并到第二个集合,(x+2N,y+2N)合并到第三个集合;
2. 如果x吃y,那么合并x-A和y-B,x-B和y-C,x-C和y-A,即(x,y+N)合并到第一个集合,(x+N,y+2N)合并到第二个集合,(x+2N,y)合并到第三个集合;
如果某个集合内的元素关系不冲突,那么这个集合就是可行的一个食物链关系。 可以看到由于我们维护集合关系的轮换性,如果第一个集合可行,那么第二,第三个集合同样可 行。同样,如果对于某一条信息,x-A的情况下在第一个集合中冲突,必有x-B在第二个集合中冲突,x-C在第三个集合中冲突。
所以,检测冲突时只需检测x-A的情况。
那么,如何检测冲突呢?
1.如果遇到第一种关系,即x,y属于同种,那么冲突的话就是有x吃y或者y吃x。
只需考虑x-A的情况,即发生了y-B,y-C的情况,具体为:(x-A,y-B)存在第一集合(x吃y已经存在),(x-A,y-C)存在第三集合(y吃x 已经存在)
2.如果遇到第二种关系,即x吃y,那么冲突的情况就是y吃x后者x与y同种。
同样只需考虑x-A的情况,即发生了y-A,y-C的情况,具体为(x-A,y-A)存在第一集合(x,y同种已经存在), (x-A,y-C)存在第三集合(y吃x已经存在)
使用并查集的same方法就能做出以上判断。
// // 088_food chain.cpp // changlle // // Created by user on 12/30/15. // Copyright (c) 2015 user. All rights reserved. // #include <iostream> using namespace std; int par[500]; int _rank[500]; //初始化元素 void init(int n) { for (int i=0;i<n;i++) { par[i]=i; _rank[i]=0; } } //查询树的根 int find(int x) { if (par[x]==x) return x; else return par[x]=find(par[x]); } //合并x,y所属的集合 void unite(int x, int y) { x=find(x); y=find(y); if (x==y) return; if (_rank[x]<_rank[y]) par[x]=y; else { par[y]=x; if(_rank[x]==_rank[y]) _rank[x]++; } } //判断x和y是否属于同一个集合 bool same(int x, int y) { return find(x)==find(y); } //以上为并查集的实现 int N=100; int K=7; int T[7]={1,2,2,2,1,2,1}; int X[7]={101,1,2,3,1,3,5}; int Y[7]={1,2,3,3,3,1,5}; int main() { init(N*3); int count=0; for (int i=0;i<K;i++){ int t=T[i]; int x=X[i]-1; int y=Y[i]-1; if (x<0 || N<=x || y<0 || N<=y){ count++; continue; } if (t==1){ //属于同一类,只需针对x=A来进行判断 if (same(x,y+N) || same(x,y+2*N)) count++; else { unite(x,y); unite(x+N,y+N); unite (x+2*N, y+2*N); } } if (t==2) { //捕食关系,同样只需针对x=A来进行判断 if (same(x,y) || same(x, y+2*N)) count++; else { unite(x,y+N); unite(x+N,y+2*N); unite(x+2*N,y); } } } cout<<count<<endl; return 0; }
相关文章推荐
- 几个著名的3D测试场景与模型
- Visual paradigm Db Archtecture Database config
- NSArray的使用
- mybatis-1
- 编译时异常 & 运行期异常
- codeforces 611B
- Reverse an ArrayList
- Binary Tree Zigzag Level Order Traversal
- appcompat_v7 报错 完美解决
- Win 10小娜给我快乐!
- maven
- Boost--内存管理--(1)智能指针
- MySQL Connector/Python 安装、测试
- python安装setuptools
- *Pow(x, n)
- 黑马程序员——常用API
- ImportError: cannot import name HTTPSHandler
- MySQL锁阻塞分析
- Linux运维面试题及解答
- [React] Extracting Private React Components