POJ 1182 食物链(种类并查集)

题目:http://poj.org/problem?id=1182

#include <iostream>
using namespace std;

const int M = 50000 + 10;

struct Node
{
    int father;
    int kind;
}node[M];

void Init(int n)
{
    for (int i = 1; i <= n; i++)
    {
        node[i].father = i;
        node[i].kind = 0;
    }

}
//
int Find(int x)
{
    if (x == node[x].father)
    {
        return x;
    }

    int temp = node[x].father;//temp保存原来的老爸

    node[x].father = Find(node[x].father);

    node[x].kind = (node[x].kind + node[temp].kind) % 3;//////////////

    return node[x].father;
}

//
void Union(int rootx, int rooty, int x, int y, int k)//k == 0:a==b  k == 1:a > b
{

    node[rooty].father = rootx;
    node[rooty].kind = (-k +(node[x].kind - node[y].kind)+3)%3;///////////////

}
//(node[a].kind - node[b].kind + 3) % 3 == 1表示a > b
//node[a].kind == node[b].kond 表示 a == b
//为了方便操作根结点的种类是0
//与根结点直接相连的节点与根结点的关系是正确的
//在同一颗树上的结点表示存在关系

int main()
{
    int n, m;
    scanf("%d%d", &n, &m);//这题只有一组数据

    int ans = 0;

    Init(n);

    while (m--)
    {
        int kind, a, b;
        scanf("%d%d%d", &kind, &a, &b);
        if (a > n || b > n)
        {
            ans++;
            continue;
        }

        if (kind == 2 && a == b)
        {
            ans++;
            continue;
        }

        int roota = Find(a);
        int rootb = Find(b);
        if (roota != rootb)
        {
            Union(roota, rootb, a, b, kind - 1);
        }
        else
        {
            if (kind == 1 && node[a].kind != node[b].kind)
            {
                ans++;
            }

            if (kind == 2 && (node[a].kind - node[b].kind + 3) % 3 != 1)
            {
                ans++;
            }
        }

    }
    printf("%d\n", ans);


    return 0;
}
原文地址:https://www.cnblogs.com/qiufeihai/p/2665906.html