poj 1182 食物链(关系并查集)
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 62824 | Accepted: 18432 |
Description
Input
Output
Sample Input
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
Sample Output
3
大体思想:
1、如果两个物种有联系,不管是吃,被吃还是同类,它们之间应该是有一条径路可达的,也就是它们在一个合集中。
2、如果a,b有关系,b,c有关系,那么a,c之间的关系式可以通过两者的关系推出来的。
下面围绕着上面的两个思想来逐一拆分。
首先就是怎么把有关系的物种放到同一个合集中去,这就要需用到并查集了。每一次入输d,x,y, 也就是相当于x,y之间有一条权为d的径路。先忽略这个权值,直接斟酌路径,那并查集的路径建立就不用我说了。一个parent数组,parent[i]表现从parent[i]到i有一条径路。那不同的食物圈就构成了一个连通区域。每个连通区域都有一个根点节。
下面斟酌怎么处理这个权
先说点数学,任何一种偏序关系都足满自反、对称、传递。
自反:自己跟自己满足偏序关系。
对称:a,b的偏序关系为r,则b,a的偏序关系为~r.表现求反。
传递:a,b的偏序关系为r1,b,c的偏序关系为r2,a,c的偏序关系为r1+r2.
为了便利,用一个relation数组来维护这个权值。relation[i]表现的是i在所的连通区域的根点节到i的关系。先略忽这个关系数组的维护过程,把团体的思绪理清晰。如果有两个物种加进来, 就有两种情况,要么它们在同一个连通集里头。要么不在同一个连通集里头。
一、两者在同一个连通集里头:
1、新加的关系表明x,y是同类,那么它们两个分别到连通区域根点节的关系应该是一样的,要不就矛盾了。(记为case1)
2、如果新加的关系表明x,y不是同类,那么在当前参加y,x相对根节点的关系和x本来相对根点节的关系应该是不变的,否则就矛盾了。(记为case2)
二、两者在不同的连通集里头:就直接连接两个连通集就能够了。(记为case3)
路径压缩处理: 由于后来物种会越来越多,我们不希望食物链拉的很长,所以会尽可能的让全部的点节都直接和根节点 相连。这样整个连通的图就有点呈现出星形。
怎么维护关系数组: 数组里头的每个元素的取值要么是0(同类),要么是1(父吃子),要么是2(子吃父)。
至于为什么要这么设置(因为题目中1表示同类,而我们定义0表示同类,相对都应该减一,所以题目中的2表示父吃子在我们这里 应该是2-1=1,,1表示父吃子),参考一另篇博客http://blog.csdn.net/c0de4fun/article/details/7318642, 这里是不能随便定义的。设前面的数据我已经处理好了,现在要处理d,x,y.为了叙说的便利,
记relation[x]为x根->x.那么在现就有三种情况:
case1:(同一个集合且同类) 这种情况x根与y根雷同。如果x根->x与y根->y不同,表明x,y不是同类,与d=1矛盾。
case2:(同一个集合但不同类) 这种情况x根与y根雷同。如果参加y之后,(x根->x) = (x根(即y根)->y + y->x),如果新求出来 的关系与本身已有的x根->x的关系不同,则矛盾。
case3:(在不同集合中) 这种情况x根与y根不同。由于这里添加的是x到y的一条有向边。将y根的父点节设置为x根,更新y根父点 节到x根的关系,即x根->y根=x根->x+x->y+y->y根,由于这里都是有向边,所以更新关系的时候注意关 系的方向。这里需要注意,我们只更新了两个根之间的关系,x根与原来的y所在的连通区域里头的节点 的关系都没有更新,这就是为什么要在一开始判断之前就要调用Find函数,更新每个点节到其根点节的 关系。
初始条件: 有了这个递推,就好办了。初始条件parent就是并查集一般的初始条件,父点节于等自己。由于初始的 时候父节点是自己,当然自己跟自己的关系肯定是同类咯,也就是relation[i]=0
#include <iostream>
#include <cstdio>
using namespace std; int father[];
int relation[];
//int d; void make_set(int n){
for(int i = ; i <= n; i++){
father[i] = i;
relation[i] = ;
}
} //更新的步调,先将当前点节与其根点节相连,然后更新其与根点节的关系
//当前节点x与根节点r的关系更新的方法:
// (x与其父点节的关系+其父点节的关系与根点节的关系)%3
//所以在更新节点x的数据之前需要更新其父节点的数据,这是find为什么搞成递归函数的原因
//其更新的次序是从根节点开始往下,始终到当前点节x的父点节。
int GetParent(int x){
if(x != father[x]){
int t = father[x];
//将当前点节的父点节设置为根点节
father[x] = GetParent(father[x]);
//更新当前节点与根节点的关系,由x->x父和x父->父根的关系是x->父根的关系
//所以在这之前必须更新其父点节与根点节的关系
relation[x] = (relation[x] + relation[t]) % ;
//father[x] = GetParent(father[x]);//写在这是错的 }
return father[x];
} void Merge_set(int x, int y, int d){
int fx = GetParent(x);
int fy = GetParent(y);
if(fx != fy){
father[fy] = fx;
relation[fy] = (relation[x] + (d - ) + ( - relation[y])) % ;
}
} int main(){
int n, k;
//cin >> n >> k;
scanf("%d %d", &n, &k);
int cnt = ;
make_set(n);
while(k--){
int d, x, y;
//cin >> d >> x >> y;
scanf("%d %d %d", &d, &x, &y); if(x > n || y > n || (d == && x == y)){
cnt++;
continue;
} int fx = GetParent(x);
int fy = GetParent(y); if(fx == fy){//属于同一个子集
//如果x,y是同类,那么他们相对根节点的关系应该是一样的
if(d == && relation[x] != relation[y])
cnt++;
//如果不是同类,加入x和y的关系之后,x相对根节点的关系(x根->y,y->x(即3-(d-1)=2).即x根->x)应该是不变的
//这里d=2表示x - y = 2-1=1;而y->x=3-(x->y)=3-1=2;
if(d == && relation[x] != (relation[y] + )%)
cnt++;
}
else{
Merge_set(x, y, d);
}
}
//cout << cnt << endl;
printf("%d\n", cnt);
return ;
}
用cin,cout会超时。。。
poj 1182 食物链(关系并查集)的更多相关文章
- POJ 1182 食物链 经典并查集+关系向量简单介绍
题目: 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有 ...
- poj 1182 食物链 (并查集)
http://poj.org/problem?id=1182 关于并查集 很好的一道题,开始也看了一直没懂.这次是因为<挑战程序设计竞赛>书上有讲解看了几遍终于懂了.是一种很好的思路,跟网 ...
- POJ 1182 食物链(并查集拆点)
[题目链接] http://poj.org/problem?id=1182 [题目大意] 草原上有三种物种,分别为A,B,C A吃B,B吃C,C吃A. 1 x y表示x和y是同类,2 x y表示x吃y ...
- POJ 1182 食物链(并查集+偏移向量)题解
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 82346 Accepted: 24616 Description ...
- POJ 1182 食物链 (并查集解法)(详细注释)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 78510 Accepted: 23396 Description ...
- POJ 1182 食物链(种类并查集)
记得第一次做这道题的时候,推关系感觉有点复杂,而且写完代码后一直WA,始终找不出错误. 在A了十几道并查集后,再做这道题,发现太小儿科了.发现原来之所以WA,就在于查找根节点时,没有同步更新子节点相对 ...
- 【POJ 1182 食物链】并查集
此题按照<挑战程序设计竞赛(第2版)>P89的解法,不容易想到,但想清楚了代码还是比较直观的. 并查集模板(包含了记录高度的rank数组和查询时状态压缩) *; int par[MAX_N ...
- POJ 1182 食物链 【并查集】
解题思路:首先是没有思路的----然后看了几篇解题报告 http://blog.csdn.net/ditian1027/article/details/20804911 http://poj.org/ ...
- poj 1182食物链(并查集)
算法思路:把那些确定了相对关系的节点放在同一棵树里(可以同时存在多棵树,单独每棵树中节点的相对关系确定),每个节点对应的 v[] 值记录他与根节点的关系( 0:同类: 1:根吃他: 2:他吃根 ).当 ...
- 洛谷 P2024 食物链 POJ 1182 Label:并查集Turbo
题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我 ...
随机推荐
- 图像特征提取三大法宝:HOG特征,LBP特征,Haar特征
(一)HOG特征 1.HOG特征: 方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子.它通过计算和 ...
- HW5.26
public class Solution { public static void main(String[] args) { int totalCount = 0; int lineCount = ...
- leetcode@ [68] Text Justification (String Manipulation)
https://leetcode.com/problems/text-justification/ Given an array of words and a length L, format the ...
- hdu4435-charge-station(搜索+贪心)
题意&题解: http://www.cnblogs.com/wuminye/p/3245546.html 说实话看了题解觉得很简单,但是比赛的时候真的是毫无头绪. 然而印象中做过一道类似的二进 ...
- 重新学习struts
这就是所谓的一边工作一边学习. 今天准备把给公司写个管理页面,按照之前的路数,写起来应该挺快,但是不太规范.也就沉下心来学习一下了. 第一个学习的是,之前,在学校,听师兄说过,对页面编码可用inter ...
- Java网络编程(模拟浏览器访问Tomcat服务器)
程序运行结果: HTTP/1.1 404 Not FoundServer: Apache-Coyote/1.1Content-Type: text/html;charset=utf-8Content- ...
- soliworks三维机柜布局(二)创建设备位置
首先声明对三维机柜布局来说,此步骤不是必须的.(创建solidworks装配体文件时,若是创建了位置就可以选择是否为每个位置创建一个装配体,没有创建位置的话只能选择创建整个工程的装配体文件) 在菜单栏 ...
- iOS开发核心语言Objective C —— 所有知识点总结
C和OC对比 OC中主要开发在什么平台上的应用程序?答:可以使用OC开发Mac OS X平台和iOS平台的应用程序 OC中新增关键字大部分是以什么开头?答:OC中新增关键字大部分是以@开头 OC中新增 ...
- 射频识别技术漫谈(1)——概念、分类
现代社会智能卡已经渗透到生活的方方面面,公交卡.考勤卡.身份证.手机卡等等数不胜数. 智能卡按使用时是否和读卡器接触可分为接触式智能卡和非接触式智能卡,接触式智能卡上有6-8个触点,使用时插在卡 ...
- prestashop二次开发 笔记(支付插件)
//主函数 public function __construct() { $this->name = 'CilPay'; //模块名称 $this->display ...