带权并查集

带权并查集

【概述】    1、定义:带权并查集即是结点存有权值信息的并查集。

      2、适用:当两个元素之间的关系可以量化,并且关系可以合并时,可以使用带权并查集来维护元素之间的关系。

      3、权值:带权并查集每个元素的权通常描述其与并查集中祖先的关系,这种关系如何合并,路径压缩时就如何压缩。

      4、与并查集的区别:带权并查集可以推算集合内点的关系,而一般并查集只能判断属于某个集合。

【具体实现】 

 

例:https://hihocoder.com/problemset/problem/1515

#include <iostream>
#include <cstdio>

using namespace std;
const int maxn=100005;
int n,m,q;
int f[maxn],v[maxn];//i的父亲,i与v[i]之间的关系;

void init()
{
    for(int i=1;i<=n;i++){
        f[i]=i,v[i]=0;
    }
}
int fin(int x)
{
    if(x!=f[x]){
        int fa=f[x];
        f[x]=fin(f[x]);
        v[x]+=v[fa];
    }
    return f[x];
}
int unit(int x,int y,int s)
{
    int fa=fin(x);
    int fb=fin(y);
    if(fa!=fb){
        f[fa]=fb;
        v[fa]=s-v[x]+v[y];
    }
}
bool same(int x,int y)
{
    return fin(x)==fin(y);
}

int main()
{
    scanf("%d%d%d",&n,&m,&q);
    int a,b,c;
    init();
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        unit(a,b,c);
    }
    for(int i=0;i<q;i++)
    {
        scanf("%d%d",&a,&b);
        if(!same(a,b)){
            printf("-1\n");
        }else{
            printf("%d\n",v[a]-v[b]);
        }
    }
    return 0;
}
posted @ 2018-09-24 16:00  Akmpfen  阅读(802)  评论(0编辑  收藏  举报