【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三个数字代表三种情况,在使用并 ...
随机推荐
- windows phone中,将crash report记录下来,写入文件,方便分析
APP出现crash(崩溃)总是不能忍的 当我们连接调试器调试的时候,发现每当APP崩溃的时候 程序都会走到App.xaml.cs中的 // Code to execute on Unhandled ...
- k-d Tree in TripAdvisor
Today, TripAdvisor held a tech talk in Columbia University. The topic is about k-d Tree implemented ...
- ZOJ 1136 Multiple (BFS)
Multiple Time Limit: 10 Seconds Memory Limit: 32768 KB a program that, given a natural number N ...
- Yii2 框架下bootstrap 弹窗预览视频等~
Yii2 本身已经引用了'yii\bootstrap\BootstrapAsset',所以使用bootstrap 非常简洁. 1 在PHP页面引用命名空间 use app\assets\AppAsse ...
- VS2012+SQL2008+ODBC编程,第一篇博客,写的不好忘各位大神指点一二~
近期写一个数据库的课程设计,用的是C++ MFC .最開始用的是ADO技术,可是苦于网上大部分的教程都是VC6.0的,对着教程敲了4,5遍还是执行不成功.我用的IDE是VS2012,毕竟VC6.0和V ...
- FineUI
window间传值: Window1.GetSaveStateReference(new string[] { TextBox1.ClientID, ak.ClientID })收 ActiveWin ...
- CSS学习笔记——盒模型,块级元素和行内元素的区别和特性
今天本来打算根据自己的计划进行前端自动化的学习的,无奈早上接到一个任务需求需要新增一个页面.自从因为工作需要转前端之后,自己的主要注意力几 乎都放在JavaScript上面了,对CSS和HTML这方面 ...
- JavaScript脚本语言的正则校验法
正则校验法有很多种类型,有些可能会比较复杂难记,我这里罗列了大家常用的几种方法,方便查询. //校验是否全由数字组成 function isShuZi(s) { var patrn=/^[0-9]{1 ...
- UMl概述(转)
1. UML的组成 UML由视图(View).图(Diagram).模型元素(Model Element)和通用机制(General Mechanism)等几个部分组成. a) 视图(View): 是 ...
- RDLC报表系列(一) 简单的动态数据绑定和配置
RDLC系列链接 RDLC报表系列(一) 简单的动态数据绑定和配置 RDLC报表系列(二) 行分组 RDLC报表系列(三) 总计和折叠 RDLC报表系列(四) 矩阵 RDLC报表系列(五) 简单的图 ...