原题链接

 

思路:

看起来并查集似乎不太好下手, 但如果我们拆成几个属性以后就方便合并了

开三倍n大小的数组, x代表x的种族, x + n代表x的猎物, x + 2 * n代表x的天敌(这里的 猎物/天敌 不仅仅是个体, 而是一个群体)

如果操作为1 x y的话, 我们就将x跟y合并, x + n跟y + n合并, x + 2 * n跟y + 2 * n合并(同类属性相同)

如果操作为2 x y的话, 我们就将

x跟y + 2 * n合并(x是y的天敌),

x + n跟y合并(x的猎物是y),

x + 2 * n跟y + n合并(x的天敌是y的猎物, 因为根据题意中的描述, 食物链是一个环, A吃B, B吃C, C吃A)

 

poj1182 食物链(带权并查集)_#includepoj1182 食物链(带权并查集)_ACM_02
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cstdio>
  5 #include <string>
  6 #include <bitset>
  7 #include <vector>
  8 #include <map>
  9 #include <queue>
 10 using namespace std;
 11 typedef long long ll;
 12 
 13 const int MAXN = 5e4 + 7, INF = 0x3f3f3f3f;
 14 int fa[4 * MAXN], ra[4 * MAXN], n, m, cnt;
 15 
 16 inline ll read()
 17 {
 18 
 19     int x = 0, f = 1;
 20     char ch = getchar();
 21     while (ch < '0' || ch > '9')
 22     {
 23         if (ch == '-')
 24             f = -1;
 25         ch = getchar();
 26     }
 27     while (ch >= '0' && ch <= '9')
 28     {
 29         x = x * 10 + ch - '0';
 30         ch = getchar();
 31     }
 32     return x * f;
 33 }
 34 
 35 int find(int x)
 36 {
 37     return x == fa[x] ? x : fa[x] = find(fa[x]);
 38 }
 39 bool unite(int x, int y)
 40 {
 41     x = find(x);
 42     y = find(y);
 43     if (x == y)
 44         return false;
 45     if (ra[x] > ra[y])
 46         swap(x, y);
 47 
 48     fa[y] = x;
 49     if (ra[x] == ra[y])
 50         ra[x]++;
 51     return true;
 52 }
 53 
 54 int main()
 55 {
 56     int ans = 0;
 57     int T, x, y, op;
 58 
 59     n = read();
 60     m = read();
 61     cnt = n;
 62     for (int i = 1; i <= 3 * n; ++i)
 63     {
 64         fa[i] = i;
 65         ra[i] = 1;
 66     }
 67 
 68     for (int i = 0; i < m; ++i)
 69     {
 70         op = read();
 71         x = read();
 72         y = read();
 73         if (x > n || y > n)
 74         {
 75             ++ans;
 76             continue;
 77         }
 78         if (op == 1)
 79         {
 80             if (find(x) == find(y + 2 * n) || find(x + 2 * n) == find(y))
 81             {
 82                 ans++;
 83                 continue;
 84             }
 85             unite(x, y);
 86             unite(x + n, y + n);
 87             unite(x + 2 * n, y + 2 * n);
 88         }
 89         else
 90         {
 91             if (find(x) == find(y) || find(2 * n + x) == find(y))
 92             {
 93                 ans++;
 94                 continue;
 95             }
 96             unite(x, y + 2 * n);
 97             unite(x + n, y);
 98             unite(x + 2 * n, y + n);
 99         }
100     }
101     printf("%d\n", ans);
102 
103     return 0;
104 }
View Code