poj 1182 食物链 并查集 题解《挑战程序设计竞赛》

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

 

 题解

可以考虑使用并查集解决 但是并不是简单的记录是否同一组的这般使用

每个动物都有三个并查集 自己 天敌 捕食 并查集

那么在获得一条信息后 我们先判断真伪

x不能吃x 自己

x y不能超过数目类型

当xy是同一类的时候  x不会出现在y的天敌和捕食并查集中(其中已经包含 y不会出现在x的天敌和捕食并查集中)

确认为真后 合并更新 x y 的同类并查集   天敌并查集和 不是并查集

 

当x吃y的信息, 则 x不会出现在y的同类和捕食并查集中(已经包含y不会出现在x同类且y不会出现在x的天敌并查集中)

确认为真后 合并更新 x和y的天敌并查集 合并更新 x的天敌与y的捕食并查集 合并更新x的捕食与y的并查集

 

代码

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <vector>
  4 
  5 
  6 using namespace std;
  7 
  8 const int MAX_N = 900010;
  9 
 10 int par[MAX_N];        //父节点
 11 int rankk[MAX_N];    //树的高度
 12 
 13 //初始化n个元素
 14 void init(int n)
 15 {
 16     for (int i = 0; i < n; i++) {
 17         par[i] = i;
 18         rankk[i] = 0;
 19     }
 20 }
 21 
 22 //查询树的根
 23 int find(int x) {
 24     if (par[x] == x) {
 25         return x;
 26     }
 27     else {
 28         return par[x] = find(par[x]);
 29     }
 30 }
 31 
 32 //合并x和y所属于的集合
 33 void unite(int x, int y) {
 34     x = find(x);
 35     y = find(y);
 36     if (x == y) return;
 37 
 38     if (rankk[x] < rankk[y]) {
 39         par[x] = y;
 40     }
 41     else {
 42         par[y] = x;
 43         if (rankk[x] == rankk[y]) rankk[x]++;
 44     }
 45 }
 46 
 47 //判断x和y是否属于同一个集合
 48 bool same(int x, int y) {
 49     return find(x) == find(y);
 50 }
 51 //=============================================================
 52 int N, K;
 53 int T[MAX_N], X[MAX_N], Y[MAX_N];
 54 
 55 void solve()
 56 {
 57     //初始化并查集
 58     //元素x ,x+N,x+2*N分别代表x-A x-B x-C
 59     init(N * 3);
 60 
 61     int ans = 0;
 62     for (int i = 0; i < K; i++) {
 63         int t = T[i];
 64         int x = X[i] - 1, y = Y[i] - 1;
 65 
 66         //不正确的编号
 67         if (x < 0 || N <= x || y < 0 || N <= y) {
 68             ans++;
 69             continue;
 70         }
 71 
 72         if (t == 1) {
 73             //xy属于同一类
 74             if (same(x, y + N) || same(x, y + 2 * N)) {
 75                 ans++;
 76             }
 77             else {
 78                 unite(x, y);
 79                 unite(x + N, y + N);
 80                 unite(x + 2 * N, y + 2 * N);
 81             }
 82         }
 83         else {
 84             //x吃y
 85             if (same(x, y) || same(x, y + 2 * N)) {
 86                 ans++;
 87             }
 88             else {
 89                 unite(x, y + N);
 90                 unite(x + N, y + 2 * N);
 91                 unite(x + 2 * N, y);
 92             }
 93         }
 94     }
 95 
 96     printf("%d\n", ans);
 97 }
 98 
 99 
100 int main()
101 {
102     cin >> N >> K;
103 
104     for (int i = 0; i < K; i++) {
105         cin >> T[i] >> X[i] >> Y[i];
106     }
107 
108     solve();
109     return 0;
110 }
View Code

 

posted on 2019-12-10 15:09  itdef  阅读(263)  评论(0编辑  收藏  举报

导航