POJ 1182 食物链 分类并查集

来源:互联网 发布:淘宝论坛官网 编辑:程序博客网 时间:2024/06/15 04:03

点击打开链接

思路通过

通过将根分成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 longusing 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;}


0 0