POJ1182食物链 (并查集)

第一反应就是和那个搞基的虫子的题很像(poj2492 http://www.cnblogs.com/wenruo/p/4658874.html),不过是把种类从2变成了3。

错在很白痴的地方,卡了好久……

代码:

/*********************************************
Problem: 1182		User: G_lory
Memory: 972K		Time: 266MS
Language: G++		Result: Accepted
*********************************************/
#include <cstdio>
#include <cstring>

using namespace std;

const int N = 50005;

int par[N];
int rank[N];
int rel[N];	// 0: same, 1: father eat son, 2: son eat father

void init(int n)
{
	for (int i = 0; i <= n; ++i) {
		par[i] = i;
		rank[i] = 0;
		rel[i] = 0;
	}
}

int find(int x)
{
	if (par[x] == x) return x;
	return find(par[x]);
}

// return 1 means root eat x, return 2 mean x eat root, return 0 mean same
int rel_root(int x)
{
	int p, ans = 0;
	for (p = x; p != par[p]; p = par[p]) {
		ans = (ans + rel[p]) % 3;
	}
	return ans;
}

void unite(int x, int y, int c)
{
	int rootx = find(x);
	int rooty = find(y);
	if (rootx == rooty) return ;
	int relx = rel_root(x);
	int rely = rel_root(y);
	if (rank[rootx] < rank[rooty]) {
		par[rootx] = rooty;
		rel[rootx] = ((rely - relx - c) % 3 + 3) % 3;
	} else {
		par[rooty] = rootx;
		rel[rooty] = ((relx - rely + c) % 3 + 3) % 3;
	}
	if (rank[rootx] == rank[rooty]) ++rank[rootx];
}

bool same(int x, int y)
{
	return find(x) == find(y);
}

int main()
{
    int n, k;
    int ch, x, y;
    scanf("%d%d", &n, &k);
		int ans = 0;
		init(n);
		for (int i = 0; i < k; ++i) {
			scanf("%d%d%d", &ch, &x, &y);
			if (x > n || x <= 0 || y > n || y <= 0) {
				++ans;
				continue;
			}
			if (ch == 1) {
				if (same(x, y)) {
					if (rel_root(x) != rel_root(y)) ++ans;
				} else unite(x, y, 0);
			} else {
				if (same(x, y)) { // x eat y
					if ( !((rel_root(x) == 0 && rel_root(y) == 1) ||
						   (rel_root(x) == 1 && rel_root(y) == 2) ||
						   (rel_root(x) == 2 && rel_root(y) == 0)) )
							++ans;
				} else unite(x, y, 1);
			}
		}
		printf("%d\n", ans);
    return 0;
}

  

并查集模板:

const int N = 300005;

int par[N];		// father
int rank[N];	// height

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;
	return par[x] = find(par[x]); // 压缩路径
}

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];
}

bool same(int x, int y)
{
	return find(x) == find(y);
}

  

时间: 2024-10-08 08:19:59

POJ1182食物链 (并查集)的相关文章

POJ1182 食物链 (并查集)*新方法

本文出自:http://blog.csdn.net/svitter 题意: 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类. 第二种说法是"2 X Y",表示X吃Y. 此人对N个动物,用上述两种说法,一句接一句地说出K句话,这

POJ1182 食物链 [并查集]

很好的题,分析与题解转自: http://blog.csdn.net/tiantangrenjian/article/details/7085575 http://blog.csdn.net/c0de4fun/article/details/7318642/ 这题不知道为啥写成多组用例不能过,,,oj的一个bug吧~ 食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 26553   Accepted: 7718 De

poj1182食物链-并查集

食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 83337   Accepted: 24925 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同

POJ1182 食物链 并查集 好题

食物链 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类. 第二种说法是"2 X Y",表示X吃Y. 此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的.当一句话满足下

编程算法 - 食物链 并查集 代码(C)

食物链 并查集 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有N仅仅动物, 分别编号为1,2,...,N. 全部动物都属于A,B,C中的一种. 已知A吃B, B吃C, C吃A. 按顺序给出两种信息K条. 第一种: x和y属于同一类. 另外一种: x吃y.  信息之间可能会出错和矛盾, 求不对的信息数. 比如: 有N=10仅仅动物, 给定K=7条信息. (1) 1: x=101, y=1; 出错:没有101的动物. (2) 2: x=1,

# [acwing 240] 食物链 [并查集]

[acwing 240] 食物链 [并查集] 传送门 题意 ABC三种动物,食物链构成一个环形,,给出M个关于彼此关系的描述,判断有多少个假话. 1 X Y表示同类 2 X Y表示X吃Y 思路 本题是并查集的一种比较新颖的用法,并查集一般用来维护集合,但是在这里主要是使用路径压缩来维护点和根之间的距离. 动物之间有三种关系(同类,捕食,被捕食),并且食物链构成环,那么可以使用和根之间的距离模3来区分三种关系,这里并不严格划分集合,主要是借助了并查集中的路径压缩. 红色的线是不存在的,只是为了方便

POJ 1182 (经典食物链 /并查集扩展)

(參考他人资料) 向量偏移--由"食物链"引发的总结 http://poj.org/problem?id=1182这道食物链题目是并查集的变型.非常久曾经做的一次是水过的,这次细致地研究了这"食物链",无非就是运用向量偏移.从曾经节点与节点转化成向量与向量的关系.我们能够把矛盾的产生得益于向量偏移时的结果. 直接引出向量偏移的运用. 以下是POJ一位大牛这样理解的,本人稍有改动. 对于集合里的随意两个元素a,b而言,它们之间必然存在着某种联系,由于并查集中的元素

POJ 1182 食物链 [并查集 带权并查集 开拓思路]

传送门 P - 食物链 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1182 Appoint description:  System Crawler  (2015-01-27) Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物

NOI 2001 食物链 /// 并查集 oj22035

Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1~N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类. 第二种说法是"2 X Y",表示X吃Y. 此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的.当一句话满足下列三条之

poj 1182 食物链 并查集好题

挑战程序设计上有解答的并查集好题.把事件作为元素进行合并,举例:若输入1 2 3,意思就是把2,3归为同一类,至于归于哪一类并不需要去讨论,则把2属于A,3属于A这两件事件归为一类;2属于B,3属于B这两件事归为一类;2属于C,3属于C这两件事归为一类:若输入 2 2 3,由于A吃B,B吃C,C吃A,就把2属于A,3属于B这两件事情归为一类:以此类推.当检测到当前情况与之前正确的情况不符合,则错误的情况数加1. #include <iostream> #include <cstdio&g