食物链--poj1182(并查集含有关系)

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

 

题意应该就不用说了

 再次回到食物链这道题,自己写了一遍,一直wa...原因竟然是不能用多实例,我也是醉了,但是我真的彻底的理解了,那些关系之间的转化,和上面那道差不多;

这道中的 r[i]表示i和f[i]之间的关系;

r[i] = 0,表示 i 和 f[i] 同类,

r[i] = 1, 表示 i 被 f[i] 吃;

r[i] = 2, 表示 i 吃 f[i];

至于为什么这样表示的看下面这些;

首先两个动物之间的关系只有三种即:同类,吃别人,被别人吃;

题中说了,如果出现 A吃B,B吃C,则 C吃A

 

下面所说的 吃 和 被吃 都是 i 对 f[i] 而言的, 吃 就是i吃f[i] ,被吃 就是i被f[i]吃;

 

同样我们可以得到 :

吃 + 吃 = 被吃;    式1;

被吃 + 吃 = 同类;  式2;

吃 + 同类 = 吃;    式3;

由上面可以看出同类用0表示,吃可以用1表示,被吃可以用2表示;

 

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <map>
#include <vector>
using namespace std;
typedef long long LL;
#define N 52100
#define met(a, b) memset(a, b, sizeof(a))
#define INF 0x3f3f3f3f

int f[N], r[N];

int Find(int x)
{
    int k = f[x];
    if(x!=f[x])
    {
        f[x] = Find(f[x]);
        r[x] = (r[x] + r[k]) % 3;
    }
    return f[x];
}

int main()
{
    int n, m, ans;

    scanf("%d %d", &n, &m);

    for(int i=0; i<=n; i++)
        f[i] = i, r[i] = 0;

    ans = 0;

    while(m --)
    {
        int op, x, y;
        scanf("%d %d %d", &op, &x, &y);

        if( x > n || y > n || (x == y && op == 2))
        {
            ans++;
            continue;
        }

        op --;///表示 x 指向 y 的关系;

        int px = Find(x);
        int py = Find(y);

        if(px != py)
        {
            f[px] = py;
            r[px] = (r[y] - op - r[x] + 3) % 3;
        }
        else if(px == py && (r[x]+op)%3 != r[y])
            ans++;
    }
    printf("%d\n", ans);
    return 0;
}

 

 

推荐一个关系推倒的其他方法的博客http://www.cnblogs.com/wuyiqi/archive/2011/08/24/come__in.html

posted @ 2015-07-26 14:47  西瓜不懂柠檬的酸  Views(181)  Comments(0Edit  收藏  举报
levels of contents