• POJ 1182 食物链 带权并查集


    今天一定彻底弄懂 带权并查集

     好吧这题我还是不懂,,,烦躁

    现在基本上知道了吧,不过不清楚公式是怎样推出来的,如果要我再写一遍的话,估计会写很多个判断

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <fstream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <deque>
     7 #include <vector>
     8 #include <queue>
     9 #include <string>
    10 #include <cstring>
    11 //#include <unordered_map>
    12 #include <map>
    13 #include <stack>
    14 #include <set>
    15 #define LL long long
    16 #define INF 0x3f3f3f3f
    17 #define OPEN_FILE
    18 #define MAXN 50005
    19 using namespace std;
    20 int n, k;
    21 int father[MAXN];
    22 int ranK[MAXN];
    23 //rank[x]表示x 与 father[x] 的关系,0 是同类,1 是 x 吃 father[x], 2 是 father[x] 吃 x
    24 int find(int x){
    25     if (x == father[x]) return x;
    26     int y = father[x];
    27     father[x] = find(father[x]);
    28     ranK[x] = (ranK[x] + ranK[y]) % 3;
    29     //rank[x]=1,rank[y]=1,表示x吃路径压缩前的的father[x]
    30     //压缩前的father[x]吃压缩后的father[x],那么就是压缩后的father[x]吃x
    31     //所以rank[x]更新为2
    32     //rank[x] = 1, rank[y] = 1 ====> rank[x] = 2
    33     //rank[x] = 1, rank[y] = 2 ====> rank[x] = 0
    34     //rank[x] = 2, rank[y] = 1 ====> rank[x] = 0
    35     //rank[x] = 0, rank[y] = 1 ====> rank[x] = 1
    36     //rank[x] = 1, rank[y] = 0 ====> rank[x] = 1
    37     //rank[x] = 2, rank[x] = 2 ====> rank[x] = 1
    38     return father[x];
    39 }
    40 void union_set(int x, int y, int z){
    41     int a = father[x], b = father[y];
    42     father[a] = b;
    43     ranK[a] = (z + ranK[y] - ranK[x] + 3) % 3;
    44     //这里仅仅是更新了father[x]的rank值, 并没有更新其他的子节点
    45     //因为每次查询时都调用了find函数,在路径压缩的回溯过程中就会将其他节点的rank值更新
    46     //如果公式看不过来的话,那就有下面这几种情况
    47     //rank[x] = 1, rank[y] = 1, z = 1 ====> rank[a] = 1
    48     //rank[x] = 0, rank[y] = 1, z = 1 ====> rank[a] = 2
    49     //因为情况比较多,就不一一列举了,但是很好奇这个公式是怎样想出来的
    50     //看到别人的博客中提到向量?
    51 }
    52 int main()
    53 {
    54 #ifdef OPEN_FILE
    55     freopen("in.txt", "r", stdin);
    56     //freopen("out.txt", "w", stdout);
    57 #endif // OPEN_FILE
    58     scanf("%d%d", &n, &k);
    59     for (int i = 1; i <= n; i++){
    60         father[i] = i;
    61     }
    62     memset(ranK, 0, sizeof(ranK));
    63     int x, y, z;
    64     int cnt = 0;
    65     for (int i = 1; i <= k; i++){
    66         scanf("%d%d%d", &z, &x, &y);
    67         if (x > n || y > n){
    68             cnt++;
    69             continue;
    70         }
    71         if (x == y && z == 2){
    72             cnt++;
    73             continue;
    74         }
    75         if (x == y) continue;
    76         int a = find(x), b = find(y);
    77         if (a == b && ranK[x] != (z - 1 + ranK[y]) % 3){
    78             //如果father[x]!=father[y],那这两个还不属于同一个集合,谈不上假话了
    79             //属于同一个集合,就有下面几种情况可以保证是真话
    80             //z - 1 = 1, rank[y] = 2, rank[x] = 0 给的条件是x吃y,而y被他们的祖先吃,那只有x和father[y]是同类才可能是真话了
    81             //z - 1 = 1, rank[y] = 0, rank[x] = 1
    82             //z - 1 = 1, rank[y] = 1, rank[x] = 2
    83             //z - 1 = 0, rank[y] = 0, rank[x] = 0
    84             //z - 1 = 0, rank[y] = 1, rank[x] = 1
    85             //z - 1 = 0, rank[y] = 2, rank[x] = 2
    86             cnt++;
    87         }
    88         if (a != b){
    89             //还不属于同一个集合的话就肯定是真话,那就把他们的关系加到集合中来
    90             union_set(x, y, z - 1);
    91         }
    92     }
    93     printf("%d
    ", cnt);
    94 }
  • 相关阅读:
    Vue源码探究-数据绑定的实现
    vue 数组遍历方法forEach和map的原理解析和实际应用
    vue 微信内H5调起支付
    uni-app官方教程学习手记
    vue-cli3 搭建的前端项目基础模板
    vue.js响应式原理解析与实现
    vue-waterfall2 基于Vue.js 瀑布流组件
    解决lucene更新删除无效的问题
    spring项目启动报错
    js监听页面copy事件添加版权信息
  • 原文地址:https://www.cnblogs.com/macinchang/p/4694362.html
Copyright © 2020-2023  润新知