poj 1182 食物链 (并查集)
http://poj.org/problem?id=1182
关于并查集 很好的一道题,开始也看了一直没懂。这次是因为《挑战程序设计竞赛》书上有讲解看了几遍终于懂了。是一种很好的思路,跟网上其他的不太一样。
因为N和K很大,所以必须高效维护动物之间的关系,并快速判断是否产生了矛盾,并查集是维护 "属于同一组"的数据结构,,但是在本题中,并不是只有属于同一类的信息,
还有捕食关系的存在,因此需要开动脑筋维护这些关系。
对于每只动物 i 创建3个元素 i-A,i-B,i-C,并用着3×N个元素建立并查集。这个并查集维护如下信息:
i-x 表示 ”i属于种类 x“;
并查集里的每一组表示组内所有元素代表的情况都同时发生或不发生。
例如,如果i-A和j-B 在同一个组里,就表示如果i属于种类A那么j一定是属于种类B,如果j属于种类B,那么i一定属于种类A,因此,对于每一条信息,只需要按照下面进行操作就可以
第一种:x和y属于同一种类,合并x-A和y-A,x-B和y-B,x-C和y-C.
第二种:x吃y 合并x-A和y-B,x-B和y-C,x-C和y-A.
不过在合并之前,需要判断合并是否会产生矛盾,例如在第一种信息的情况下,需要检查比如x-A和y-B或者y-C是否在同一组的等信息。
#include <cstdio>
const int maxn = ; int par[maxn]; //父亲
int rank[maxn]; //树的高度 int N,K;
int T[maxn],X[maxn],Y[maxn]; //T是类型
//初始化n个元素
void init(int n) {
for(int i=; i<n;i++) {
par[i]=i;
rank[i]=;
}
}
//查询树的根
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);
} void solve() {
//初始化并查集
//元素 x,x+N,x+2*N分别代表x-A,x-B,x-C
init(N*); int ans=;
for(int i=;i<K;i++) {
int t=T[i];
int x=X[i]-,y=Y[i]-;
if(x<||N<=x||y<||N<=y) { //不正确的编号
ans++;
// printf("%d %d\n",x,y);
continue;
} if(t==) {
//x和y属于同一类 并且每次都是3个集合一起合并,所以只需要判断一种情况即可。
if(same(x,y+N)||same(x,y+*N)) { //竟然x和y是同一种类,那么x和y+N,x和y+2N必定不能是同一种
ans++;
}
else { //合并 两个种类,注意我们不清楚 x和y具体是哪个种类,所以必须全部合并
unite(x,y);
unite(x+N,y+N);
unite(x+N*,y+N*);
}
}
else {
//x吃y
if(same(x,y)||same(x,y+*N)) { //x和y在同一组,或者是A,C的情况
ans++;
}
else { //A吃B,B吃C,C吃A
unite(x,y+N);
unite(x+N,y+*N);
unite(x+*N,y);
}
}
}
printf("%d\n",ans);
} int main() {
//freopen("a.txt","r",stdin);
scanf("%d%d",&N,&K);
for(int i=;i<K;i++)
{
scanf("%d%d%d",&T[i],&X[i],&Y[i]);
// printf("%d %d %d\n",T[i],X[i],Y[i]);
}
solve();
return ;
}
poj 1182 食物链 (并查集)的更多相关文章
- POJ 1182 食物链 [并查集 带权并查集 开拓思路]
传送门 P - 食物链 Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u Submit ...
- poj 1182 食物链 并查集 题解《挑战程序设计竞赛》
地址 http://poj.org/problem?id=1182 题解 可以考虑使用并查集解决 但是并不是简单的记录是否同一组的这般使用 每个动物都有三个并查集 自己 天敌 捕食 并查集 那么在获得 ...
- POJ 1182 食物链(并查集的使用)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 81915 Accepted: 24462 Description ...
- poj 1182 食物链 并查集的又一个用法
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 41584 Accepted: 12090 Descripti ...
- POJ 1182食物链(并查集)
食物链Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 85474 Accepted: 25549Description动物王国中有三 ...
- POJ - 1182 食物链 并查集经典
思路:设r(x)表示节点x与根结点的关系,px表示x的根结点.记录每个节点与其父节点的关系,就能很方便知道每个节点以及和它的父节点的关系. struct node{ int par; //父亲节点 i ...
- poj——1182食物链 并查集(提升版)
因为是中文题,题意就不说了,直接说思路: 我们不知道给的说法中的动物属于A B C哪一类,所以我们可以用不同区间的数字表示这几类动物,这并不影响结果,我们可以用并查集把属于一类的动物放在一块,举个例子 ...
- POJ 1182 食物链 (并查集)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 50601 Accepted: 14786 Description ...
- POJ 1182 食物链(并查集)
题目链接 经过宝哥的讲解,终于对这种问题有了进一步的理解.根据flag[x]和flag[y]求flag[tx]是最关键的了. 0吃1,1吃2,2吃0. 假设flag[tx] = X; 那么X + fl ...
- poj 1182 (关系并查集) 食物链
题目传送门:http://poj.org/problem?id=1182 这是一道关系型并查集的题,对于每个动物来说,只有三种情况:同类,吃与被吃: 所以可以用0,1,2三个数字代表三种情况,在使用并 ...
随机推荐
- JSP页面批量选择&全选操作&选择回显
效果如下: js验证部分: 页面body部分: 附:控制器Controller中验证批量选择条件回显:
- String str=new String("a")和String str = "a"有什么区别?
问:String str=new String("a")和String str = "a"有什么区别? 答:String str = "a" ...
- nsight 初级使用指南
1.安装,没有什么特殊设置 2.打开vs,编译生成你需要分析的.exe,在vs上方菜单,有nsight menu, choose Start Graphics Debugging. 3.在弹出对话框中 ...
- JavaScript之setcookie()讲解
function setcookie(name,value){ var Days = 30; var exp = new Date(); exp ...
- C语言预处理命令
1.#error Directive (C/C++) The #error directive emits a user-specified error message at compile time ...
- KMP--路过
HDU 1358:弄清楚了NEXT,就好解决,还有不要再循环中用strlen;会超 ----------------------我是凑字数的------------------还是不会KMP----- ...
- Python:异常处理
Python 是面向对象的语言,所以程序抛出的异常也是类. 一.常见的异常类 NameError:尝试访问一个没有申明的变量 ZeroDivisionError:除数为 0 SyntaxError:语 ...
- 充分发挥异步在 ASP.NET 中的强大优势
作者:Brij Bhushan Mishra 最近几年,异步编程受到极大关注,主要是出于两个关键原因:首先,它有助于提供更好的用户体验,因为不会阻塞 UI 线程,避免了处理结束前出现 UI 界面挂起. ...
- photosop快速对白色背景图片进行抠图
因为其中有个作业,做个图书馆的小网页.所以打算取图书馆logo上面那几个字. 图片如下: 因为是白色背景,一开始打算使用魔棒工具,不过效果不好. 后来百度了下,使用色彩范围可以快速抠图 打开photo ...
- C++堆栈与函数调用
一.C++程序内存分配 1)在栈上创建.在执行函数时,函数内局部变量的存储单元都在栈上创建,函数结束是,这些存储单元自动被释放.栈内存的分配运算内置于处理器的指令集中,一般采用寄存器来存取,效率很高但 ...