1. 程式人生 > >poj-1182-食物鏈(並查集)

poj-1182-食物鏈(並查集)

題目地址

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

解題思路

  1. 對於每隻動物i創造三個元素i-A, i-B, i-C, 並用這3*N個元素建立並查集。
    • i-x表示“i屬於種類x”
    • 並查集裡的每一組內所有元素代表的情況都同時發生或不發生
  2. 例如,如果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
  3. 在合併之前,判斷是否會有矛盾。

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; }