poj-1182-食物鏈(並查集)
阿新 • • 發佈:2018-11-06
題目地址
http://poj.org/problem?id=1182
解題思路
- 對於每隻動物i創造三個元素i-A, i-B, i-C, 並用這3*N個元素建立並查集。
- i-x表示“i屬於種類x”
- 並查集裡的每一組內所有元素代表的情況都同時發生或不發生
- 例如,如果i-A和j-B在同一個組裡,那麼就表示如果i屬於種類A那麼j一定屬於種類B,如果j屬於 種類B那麼i一定屬於種類A。所以:
- x,y同一類—–合併x-A和y-A, x-B和y-B,x-C-和y-C
- x吃y————合併x-A和y-B, x-B和y-C,x-C-和y-A
- 在合併之前,判斷是否會有矛盾。
Code
#include <iostream>
#include <stack>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <map>
#include <queue>
#include <vector>
#include <algorithm>
#define INF 0x3fffffff
#define N 50005
#define K 100005
using namespace std;
int n, k;
int fa[3*N];
int rk[3*N];
void init() {
for (int i = 0; i < 3*n; i++) {
fa[i] = i;
rk[i] = 0;
}
}
int _find(int x) {
if (x == fa[x]) return x;
else return fa[x] = _find(fa[x]);
}
void _union(int x, int y) {
x = _find(x);
y = _find(y);
if (x == y) return;
if (rk[x] < rk[y]) {
fa[x] = y;
} else {
fa[y] = x;
if (rk[x] == rk[y]) rk[x]++;
}
}
bool same(int x, int y) {
return _find(x) == _find(y);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
scanf("%d%d", &n, &k);
init();
int ans = 0;
for (int i = 0; i < k; i++) {
int d, x, y;
scanf("%d%d%d", &d, &x, &y);
x--; y--;
if (!(0 <= x && x < n && 0 <= y && y < n)) {
ans++;
continue;
}
if (d == 1) {
if (same(x, y+n) || same(x, y+2*n)) {
ans++;
} else {
_union(x, y);
_union(x+n, y+n);
_union(x+2*n, y+2*n);
}
} else {
if (same(x, y) || same(x, y+2*n)) {
ans++;
} else {
_union(x, y+n);
_union(x+n, y+2*n);
_union(x+2*n, y);
}
}
}
cout << ans << endl;
return 0;
}