ACM/ICPC 之 并查集-食物链(POJ1182)

时间:2023-12-23 11:24:44

  并查集的经典题型,POJ上题目还是中文= =,一般看到中文题都会感觉不太简单,这道题的数学归纳用得比较多,可以简化代码,挺有意思的。

  同类型的题目还有POJ1703,比这个要简单,想了解并查集基本介绍或想参考Code请移步:算法手记 之 数据结构(并查集详解)(POJ1703)

  


  存在食物链: A吃B,B吃C,C吃A

  给出两种判断:1 a b  指a和b相同

         2 a b  指a吃b

  现依照题目输入,输出判断的错误次数:1.a,b超过N错误

                    2.a,b不符合前面判断则错误

  Code仅供参考:

  

 //食物链:A吃B,B吃C,C吃A
//r[]中:0为同类,1为父亲吃自己,2为自己吃父亲
//Time:204Ms Memory:556K
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAX 50005
int n, k;
int fa[MAX], r[MAX]; //father node - ralation
int fake; //假话总数
int find(int x)
{
if (x != fa[x])
{
int tmp = fa[x];
fa[x] = find(fa[x]); //压缩路径
r[x] = (r[x] + r[tmp]) % ; //归纳得出
}
return fa[x];
}
int main()
{
scanf("%d%d", &n, &k); for (int i = ; i <= n; i++)
fa[i] = i; //将父结点设为自己
for (int i = ; i < k; i++)
{
int flag, a, b;
scanf("%d%d%d", &flag, &a, &b);
if (a > n || b > n)
{
fake++;
continue;
}
int pa = find(a), pb = find(b);
if (flag == )
{
if (pa != pb)
{
fa[pa] = pb;
r[pa] = (r[b] - r[a] + ) % ; //归纳得出
}
else if (r[a] != r[b])
fake++;
}
else {
if (pa != pb) {
fa[pa] = pb;
r[pa] = (r[b] - r[a] + ) % + ; //归纳得出
}
else if ((r[a] - r[b] + ) % != ) //归纳得出
fake++;
}
}
printf("%d\n", fake);
return ;
}