poj 1182 食物链

经典经典并查集!!!!

强烈建议自己写一遍,真是。。

其实重点就是偏移量的更新。ps可以用向量解。

传送传送戳

推荐并查集讲得很好玩的戳

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;
 int n,k,i,num,r1,r2,d,x,y;
 /*relaton = 0,同类; relation=1,被父节点吃; relationg=2,吃父节点;*/ 
struct node
{

 int parent;
 int relation;
}p[50010];

int find(int x)

{
    int t;
    if(p[x].parent==x) return x;
    else
    {
        t=p[x].parent; 
        p[x].parent=find(t);
        p[x].relation=(p[t].relation+p[x].relation)%3;
}

    return p[x].parent;
    /*说明: 在查找之前,x的父亲节点是fx;假设p[x].relation=0(即r和父亲同类), p[x].relation=1(也就是fx被fxx吃;经过路径压缩,r的父亲节点变为fxx; 所以更新关系应该为up;*/ 

}

void join()

{
    p[r1].parent=r2; 
    p[r1].relation=(3+d-1+p[y].relation-p[x].relation)%3;
    /*if p[x].relation=0 p[y].relation=1(即rooty吃y),则有:\ 1>输入d=1时,可以推出rooty吃rootx, 即p[rooty].relation=2; 2>输入d=2时,即输入的x吃y,可以推出rooty与rootx是同类(因为rooty吃y,x吃y, 则rooty与x是同类,又rootx与x是同类),即p[rooty].relation=0; +3是为了判负数;*/

}

int main()

{
    scanf("%d%d",&n,&k);
    for(i=1;i<=n;i++)//初始化 
    {
     p[i].parent=i;
     p[i].relation=0;
    }
    num=0;
    while(k--)
    {
     scanf("%d%d%d",&d,&x,&y);
     if(x>n||y>n||(d==2&&x==y))  num++;
    else
     {
         r1=find(x);
        r2=find(y);
         if(r1!=r2)
        join();
        else 
         {
             if(d==1&&p[x].relation!=p[y].relation) num++;
             else if(d==2&&(p[x].relation-p[y].relation+3)%3!=1) num++;
         }
     }
    }
    printf("%d\n",num);
    return 0;

}

你可能感兴趣的:(poj)