zoukankan      html  css  js  c++  java
  • 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
    ", 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
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    Java之抽象类,多态,接口
    Java之抽象类,多态
    Java之类。实例初始化
    Java基础之继承
    java面向对象之工具类
    Java基础面向对象封装
    Python入门学习资料推荐
    内网安全「攻防」学习指南
    windows文件扩展名
    java 的包命名规范
  • 原文地址:https://www.cnblogs.com/itdef/p/12016795.html
Copyright © 2011-2022 走看看