POJ - 1182 - 食物链 (带权并查集)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sugarbliss/article/details/89488732

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

思路:带权并查集,主要是关系的定义,题目中给了A吃B, B吃C,C吃A,所以我们根据这个来定义关系:

  • 0 : X被Y吃
  • 1 : X和Y同类
  • 2 : X吃Y

也可以定义0:同类 1:吃 2:被吃,只不过权值的关系不一样,中心还是要围绕A吃B, B吃C,C吃A这个定义。无论哪种定义,权值初始化一定要符合你定义的关系,第一种权值数组要初始化为1,第二种要初始化为0,f[i]=i,表示同类。

#include <stdio.h>
#include <string.h>
using namespace std;
const int N = 1e5+7;
int f[N], w[N], ans, n, k;
void init()
{
    for(int i = 0; i <= n; i++)
        f[i] = i, w[i] = 1;
}
int findd(int x)
{
    if(f[x] == x) return x;
    int t = f[x];
    f[x] = findd(f[x]);
    w[x] = (w[x] + w[t] + 2 + 3) % 3;
    return f[x];
}
void unint(int d, int x, int y)
{
    int tx = findd(x), ty = findd(y);
    if(tx != ty)
    {
        f[tx] = ty;
        w[tx] = (-w[x] + w[y] + d + 3) % 3;
    }
    else
    {
        if(((w[x] - w[y]  + 1 + 3) % 3 ) != d) ans++;
    }
}

int main()
{
    scanf("%d%d",&n, &k);
    int d, x, y; init();
    while(k--)
    {
        scanf("%d%d%d",&d, &x, &y);
        if(x > n || y > n || (d == 2 && x == y)) ans++;
        else unint(d, x, y);
    }
    printf("%d\n",ans);
}
/*
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
*/

猜你喜欢

转载自blog.csdn.net/sugarbliss/article/details/89488732