POJ 1182 食物链

并查集的应用。

题意略。

题解:用数组a来表示x节点与父节点的关系,Union操作和Find操作看代码。

    a[x] = 0 父子同类
    a[x] = 1 子吃父
    a[x] = 2 父吃子


#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 50005;
int set[MAXN], a[MAXN];
int f1[3][3] = {{0, 1, 2}, {2, 0, 1}, {1, 2, 0}};
int f2[3][3] = {{1, 2, 0}, {0, 1, 2}, {2, 0, 1}};

int find(int x) {
    if (set[x] == x) return x;
    int t = find(set[x]);
    a[x] = (a[set[x]]+a[x])%3;
    return set[x] = t;
}
void Union(int x, int y, int d) {
    int fx = find(x);
    int fy = find(y);
    set[fx] = fy;
    if (d == 1) a[fx] = f1[a[x]][a[y]];
    else a[fx] = f2[a[x]][a[y]];
}
int main() {
    int n, k, d, x, y;
    int fx, fy;
    int ans = 0;

    scanf("%d %d", &n, &k);
    memset(a, 0, sizeof(a));
    for (int i=1; i<=n; i++) set[i] = i;
    while ( k-- ) {
        scanf("%d %d %d", &d, &x, &y);
        if (x>n || y>n || (d==2 && x==y)) {
            ans++;
            continue;
        }
        fx = find(x);
        fy = find(y);
        if (fx == fy) {
            if (d==1 && a[x]!=a[y]) {
                ans++;
                continue;
            }
            if (d==2 &&
                ((a[x]==0&&a[y]!=2)||(a[x]==1&&a[y]!=0)||(a[x]==2&&a[y]!=1))) {
                ans++;
                continue;
            }
        } else Union(x, y, d);
    }
    printf("%d\n", ans);
    return 0;
}


你可能感兴趣的:(POJ 1182 食物链)