POJ 1182 食物链

走你:http://poj.org/problem?id=1182

详情写在代码里了。有疑问请评论


#include <stdio.h>
#include <algorithm>
#include <string.h>
#define MAXN 50010
using namespace std;
int r[MAXN],k,lie,f[MAXN],n;
void init()
{
    int i;
    //printf("init is right\n");
    for(i=1; i<=n; i++)
    {
          /*r[]表示每个节点与其对应的根节点之间的关系, 0表示同类 1表示被父节点吃 2表示吃父节点*/
        f[i] = i;   //父节点一开始全是自己
        r[i] = 0;   //自己跟自己一定是同类吧
    }
}
int find_father(int x)
{
    if(x == f[x])
        return x;
    int t= f[x];                //记录x的父节点
    f[x] = find_father(f[x]);   //找到X的祖宗节点
    r[x] = (r[x]+r[t])%3;       //更新 x 与父节点之间的关系
    /* 我们假设 x 与 y的关系r1,y 与 z关系r2 x 与 z的关系为 (r1+r2)%3 */
    return f[x];
}
void uninon(int x,int y,int d)
{
    int fx= find_father(x);
    int fy= find_father(y);

    f[fy]= fx;
    r[fy]= (3-r[y]+(d-1)+r[x])%3;

    /*fx为x的根,fy为y的根 合并时要把fx设置为fy的父节点 fy 对 y的关系为 (3-r[y])%3 y 对 x的关系为 d-1 x 对 fx 的关系 r[x] 所以fy 对应fx的关系为(3-r[y]+r[x]+d-1)%3 */
}
int main()
{
    scanf("%d %d",&n,&k);//带权并查集 这题 的坑点在这,他不用多组测试数据
    init();
    lie=0;
    int op,x,y;
    for(int i=0; i<k; i++)
    {
        //printf("lie is %d\n",lie);
        scanf("%d %d %d",&op,&x,&y);

        if(x>n||y>n||(op==2 && x==y))
            lie++;
        else if(find_father(x) == find_father(y))
        {
            if(op==1 && r[x]!=r[y] )
                lie++;
            if(op==2 && (r[x]+1)%3 !=r[y])
                lie++;
        }
        else uninon(x,y,op);
    }
    printf("%d\n",lie);
    return 0;
}

你可能感兴趣的:(poj,并查集,OJ)