码迷,mamicode.com
首页 > 其他好文 > 详细

并查集

时间:2020-01-19 23:43:08      阅读:92      评论:0      收藏:0      [点我收藏+]

标签:方便   find   str   out   +=   return   int   ace   表示   

技术图片

void init() {
    for(int i = 1; i <= N; i++)
        f[i] = i;
}

int find(int k) {
    return f[k] == k? k : f[k] = find(f[k]);
}

int union(int a, int b) {
    f[find(b)] = find(a);
}

 

带权并查集

假定a、b是两个结点且a > b,a -> b表示区间[b, a)的和,b -> a表示负的区间[b, a)的和。
需要将结点对转化为一种左开右闭的形式以方便连接。

假设W1是要添加的边,W4是实际添加的边,它们之间的关系如下图所示。

技术图片

 对于路径压缩,直接累加各边权即可。

例题:HDU3038
http://acm.hdu.edu.cn/showproblem.php?pid=3038

//样例输入
10 5
1 10 100
7 10 28
1 3 32
4 6 41
6 6 1
 
//样例输出
1

将这个求解过程可视化。

技术图片

#include<bits/stdc++.h>
using namespace std;

int f[200010], w[200010];

int find(int k) {
    if(k != f[k]) {
        int a = find(f[k]);
        w[k] += w[f[k]];
        f[k] = a;
    }
    return f[k];
}

int N, M, A, B, S;
int main() {
    while(~scanf("%d%d", &N, &M)) {
        for(int i = 1; i <= N + 1; i++) {
            f[i] = i;
            w[i] = 0;
        }
        int ans = 0;
        while(M--) {
            scanf("%d%d%d", &A, &B, &S);
            B++;
            int Aa = find(A), Ba = find(B);
            if(Aa != Ba) {
                f[Ba] = Aa;
                w[Ba] = S + w[A] - w[B];
            }
            else if(w[B] - w[A] != S) ans++;
        }
        cout << ans << endl;
    }
}

并查集

标签:方便   find   str   out   +=   return   int   ace   表示   

原文地址:https://www.cnblogs.com/nioh/p/12215866.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!