您的位置:首页 > 其它

POJ 1182 食物链 分类并查集

2016-02-22 23:11 253 查看
点击打开链接

思路通过

通过将根分成3部分

应该也是属于分组并查集(种类并查集)。

对于这道题目,我们可以这样来理解,

建立3个集合A,B,C,

集合A表示和a是同一种类的元素,

集合B表示的是与 “a吃的元素” 是同一种类的元素,

集合C表示的是与 “吃a的元素” 是同一种类的元素。详细解释附在代码中。

三个集合{元素|1~3*n}其中对于任意一个集合,集合中元素(1~n)吃(n+1~2*n),(n+1~2*n)吃(2*n+1~3*n),(2*n+1~3*n)吃(1~n).

对于x和y 是同类.并且x和y不再一个结合的情况下,判断(y+n)、(y+2n)是否和x在一个集合,若都不是,那么(x,y)并成一个集合.(x+n,y+n)并成一个集合.(x+2*n,y+2*n)并成一个集合.

对于x 吃 y.如果x 和 (y+n)不再一个结合的情况下,判断 y、(y+2*n) 是否和 x 是在一个集合,若都不是,那么(x,y+n)并成一个集合.(x+n,y+2*n)并成一个集合.(x+2*n,y)并成一个集合.

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#define LL long long
using namespace std;
int bin[160000];
int Find(int x)
{
return x==bin[x]?x:bin[x]=Find(bin[x]);
}
void Union(int x,int y)
{
int fx=Find(x);
int fy=Find(y);
if(fx!=fy)
bin[fx]=fy;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1; i<=3*n; i++)
bin[i]=i;
int num=0;
for(int i=0; i<m; i++)
{
int d,x,y;
scanf("%d%d%d",&d,&x,&y);
if(x>n||y>n||x<1||y<1)
{
num++;
continue;
}
if(d==1)
{      ///x吃y的关系              y吃x
if(Find(x)==Find(y+n)||Find(x)==Find(y+2*n))
num++;
else
{   ///建立同类的关系
Union(x,y);
Union(x+n,y+n);
Union(x+2*n,y+2*n);
}
}
else
{
///同类              y吃x
if(Find(x)==Find(y)||Find(x)==Find(y+2*n))
num++;
else
{  ///建立x吃y的关系
Union(x,y+n);
Union(x+n,y+2*n);
Union(x+2*n,y);
}
}
}
printf("%d\n",num);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: