【POJ 1182 食物链】并查集
此题按照《挑战程序设计竞赛(第2版)》P89的解法,不容易想到,但想清楚了代码还是比较直观的。
并查集模板(包含了记录高度的rank数组和查询时状态压缩)
const int MAX_N=*;
int par[MAX_N];
int rank[MAX_N];
//初始化,根为自身,高度为0
void init(int scab)
{
for(int i=;i<=scab;i++)
{
par[i]=i;
rank[i]=;
}
}
//查找,途径的所有结点都直接连到根上
int find(int x)
{
if(par[x]==x) return x;
return par[x]=find(par[x]);
}
//合并,把短链连接到长链上,保持结点高度的相对关系
int unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y) return ;
if(rank[x]<rank[y]) {par[x]=y; return ;}
par[y]=x;
if(rank[x]==rank[y]) rank[x]++;
return ;
}
并查集实现
并查集是用于维护“属于同一集合”的数据结构,然而这道题的“属于同一集合”并不指“是同类”,而是指“这几个情况若发生必然同时发生”。
我们从理解题意开始:
有N只动物,分别编号为1,2,...,N。所有动物属于A,B,C类中的一种,类之间有天然的A吃B,B吃C,C吃A的关系。
按如下两种格式顺序给出共K条信息(只表达了相对关系):
1 x y: x,y是同类
2 x y: x吃y
每条信息若不符合常理(编号大于N,或自己吃自己)或与已有信息矛盾,则为错误。
问这K条信息有几条错误?
由于A,B,C之间的吃与被吃关系构成一个循环,所以三类的等级关系根本上也是相对的,那么每条信息都可以翻译成三种可能的实际情况。同时维护这三种可能
,就需要为每个动物x分配三个数组元素,分别表示x是A,x是B,x是C这三个事件。
同属一个集合的事件意味着“若发生必然同时发生”。
并查集需要用一个数组存储每个元素“属于哪一集合”,那么可以开一个长度为N*3的数组,用x,x+N,x+N*2分别表示x是A,x是B,x是C。
表示x与y是同类,需要维护这三种可能
unite(x,y); //x,y都是A
unite(x+n,y+n); //x,y都是B
unite(x+2*n,y+2*n); //x,y都是C
表示x吃y,需要维护这三种可能
unite(x,y+n); //x是A,y是B
unite(x+n,y+2*n); //x是B,y是C
unite(x+2*n,y); //x是C,y是A
想清楚了道理,代码就比较好理解了。注意由于从始至终只知道相对关系,同时维护了三种可能,所以判断矛盾的时候任选一种判断就可以了。
int main()
{
freopen("e.txt","r",stdin);
scanf("%d%d",&n,&k);
ans=;
init(n*);
while(k--)
{
scanf("%d%d%d",&d,&x,&y);
if(x>n||y>n)
{
ans++;
continue;
}
if(d==)
{//若想成为同类,就不可能有x吃y或y吃x的关系
if(find(x)==find(y+n)||find(y)==find(x+n))
ans++;
else
{
unite(x,y);
unite(x+n,y+n);
unite(x+*n,y+*n);
}
}
else if(d==)
{
if(x==y) ans++;
//若想x吃y,则x,y不可能是同类,也不可能y吃x
else if(find(x)==find(y)||find(y)==find(x+n))
ans++;
else
{
unite(x,y+n);
unite(x+n,y+*n);
unite(x+*n,y);
}
}
}
printf("%d\n",ans);
return ;
}
OJ运行结果如下:

这道题使我对并查集有了新的认识,想清楚“同属一个集合”代表什么很重要,不一定就是题目限定的“属于同一种”。
分析问题的难度有时会大于编程的难度,如果说代码能力可以通过刷题习得,那么分析问题的能力真的需要足够的知识储备和一些“创造性思维”了。
【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三个数字代表三种情况,在使用并 ...
随机推荐
- 《how to design programs》第11章自然数
这章让我明白了原来自然数的定义本来就是个递归的过程. 我们通常用枚举的方式引出自然数的定义:0,1,2,3,等等(etc).最后的等等是什么意思?唯一能把等等从描述自然数的枚举方法中去除的方法是自引用 ...
- 使用achartengine实现自定义折线图 ----附代码 调试OK
achartengine作为android开发中最常用的实现图标的开源框架,使用比较方便,参考官方文档谢了如下Demo,实现了自定义折线图. package edu.ustb.chart; impor ...
- tr 替换删除字符
1.关于tr 通过使用 tr,您可以非常容易地实现 sed 的许多最基本功能.您可以将 tr 看作为 sed 的(极其)简化的变体:它可以用一个字符来替换另一个字符,或者可以完全除去一些字符.您 ...
- 《深入了解 Linq to SQL》之对象的标识 —— 麦叔叔呕心呖血之作
序言 很多朋友都向我提过,希望我写一下关于Linq to SQL 或者 VS 插件方面的文章.尽管市面上有很多 Linq to SQL 的书籍,但是都是介绍怎么用,缺乏深度.关于 VS 插件方面的书籍 ...
- Clone Graph 解答
Question Clone an undirected graph. Each node in the graph contains a label and a list of its neighb ...
- EasyUI DataGrid定制默认属性名称
EasyUI DataGrid绑定服务器返回Json数据的解决方案 1. 服务器返回的数据对象格式,及初始化返回值 public class RequestResult { private int c ...
- Handshakes(思维) 2016(暴力)
Handshakes Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu Submit Sta ...
- iOS获取UIView上某点的颜色值
项目需求中遇到获取UIView上某个坐标点的RGB颜色值的需求,现在把自己找到的解决方案简单总结记录一下,遇到了下面的情况: 不可移动的UIView 旋转式的UIView 滑条式的UIView 不可移 ...
- Spring 入门 Ioc-Annotation
通过对XML版本进行修改:http://www.cnblogs.com/likailan/p/3446821.html 一.导入 Spring 所需要的包 spring-framework-2.5.6 ...
- 多线程程序中fork导致的一些问题
最近项目中,在使用多线程和多进程时,遇到了些问题. 问题描述:在多线程程序中fork出一个新进程,发现新的进程无法正常工作. 解决办法:将开线程的代码放在fork以后.也就是放在新的子进程中进行创建. ...