带权值的并查集

博文:https://blog.csdn.net/yjr3426619/article/details/82315133

带全并查集

路径压缩,表达每个当前node与 当前node所在的并查集的root 之间的关系

并查集一定是单向连通的,所以一些node处理时 【node1,node2】 weight 可能需要把 一端的闭区间变为开区间

俩个相对信息求出绝对信息   --水题

例题 : HDU 3038

//带权值并查集
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2e5 + 25;
int dis[maxn];
int p[maxn];
int find(int u)//寻根
{
    if(u!=p[u])
    {
        int tmp = p[u];//保存原来的根节点
        p[u] = find(p[u]);//路径压缩
        dis[u] += dis[tmp];//dis[tmp] 已经为tmp(即原来父节点)到根节点的距离所以加上本身自身到tmp的dis则为u到root的dis
    }
    return p[u];
}
void merge(int u,int v,int value)
{
    int f1 = find(u);
    int f2 = find(v);
    p[f1] = f2;
    dis[f1] = value + dis[v] - dis[u];
}//带权并查集合并
int main()
{
    int n,m;//n节点,m条边
    while(cin>>n>>m)
    {
        int ans = 0,u,v,value;
        for(int i=0;i<=n;++i)
        {
            dis[i] = 0;
            p[i] = i;
        }
        while(m--)
        {//图改成了从0开始(important)
            cin>>u>>v>>value;
            --u;
            if(find(u)==find(v))
            {
                if((dis[u]-dis[v])!=value)
                    ++ans;
            }else{
                merge(u,v,value);//否则合并
            }
        }
        cout<<ans<<endl;
    }
}

hihoCoder 1515

//带权并查集
#include<iostream>
#include<cstdio>//不是同一集合,合并,否则不做操作
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e5 + 15;
int dis[maxn],p[maxn];//当前node到root的距离
int find(int u)
{
    if(u!=p[u])
    {
        int tmp = p[u];
        p[u] = find(p[u]);
        dis[u] += dis[tmp];
    }
    return p[u];
}
int main()
{
    int n,m,q;//n个节点,m条边,q个查询
    while(cin>>n>>m>>q)
    {
        for(int v=1;v<=n;++v)
        {
            dis[v] = 0;
            p[v] = v;
        }
        int u,v,value;
        while(m--)
        {
            cin>>u>>v>>value;
            int f1 = find(u);
            int f2 = find(v);
            if(f1!=f2)
            {
                p[f1] = f2;
                dis[f1] = value + dis[v] - dis[u];
            }
        }
        while(q--)
        {
            cin>>u>>v;
            if(find(u)!=find(v))
                cout<<-1<<endl;
            else
                cout<<dis[u] - dis[v]<<endl;
        }
    }
}

  

原文地址:https://www.cnblogs.com/newstartCY/p/11601164.html

时间: 2024-11-08 11:45:57

带权值的并查集的相关文章

HDU 1863:畅通工程(带权值的并查集)

畅通工程 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 16075    Accepted Submission(s): 6677 Problem Description 省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可).经过调查评估,得到的统计表中列出

HDU 1863:畅通project(带权值的并查集)

畅通project Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 16075    Accepted Submission(s): 6677 Problem Description 省政府"畅通project"的目标是使全省不论什么两个村庄间都能够实现公路交通(但不一定有直接的公路相连,仅仅要能间接通过公路可达就可以).经过

POJ 2492(权值向量并查集)

A Bug's Life Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 49835   Accepted: 16094 Description Background Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they feature two different gender

nyoj-----284坦克大战(带权值的图搜索)

坦克大战 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 Many of us had played the game "Battle city" in our childhood, and some people (like me) even often play it on computer now. What we are discussing is a simple edition of this game. Given a map that co

hdu 4771 Stealing Harry Potter&#39;s Precious (2013亚洲区杭州现场赛)(搜索 bfs + dfs) 带权值的路径

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4771 题目意思:'@'  表示的是起点,'#' 表示的是障碍物不能通过,'.'  表示的是路能通过的: 目的:让你从 '@' 点出发,然后每个点只能走一次,求出最小的距离: 解题思路:先用 bfs 求解出任意两点之间的距离,用 ans[i][j],表示点 i 到点  j 的距离: 然后用 dfs 递归求出从起点经过所有点的距离中,比较出最小的: AC代码: 1 #include<iostream>

跟着chengyulala刷题之[kuangbin带你飞]之&#39;并查集&#39;专题/斜眼笑

[kuangbin带你飞] 专题1-23 https://vjudge.net/article/187 专题五 并查集 POJ 2236 Wireless Network  http://poj.org/problem?id=2236POJ 1611 The Suspects  http://poj.org/problem?id=1611HDU 1213 How Many Tables  http://acm.hdu.edu.cn/showproblem.php?pid=1213HDU 3038

[POJ 1988] Cube Stacking (带值的并查集)

题目链接:http://poj.org/problem?id=1988 题目大意:给你N个方块,编号从1到N,有两种操作,第一种是M(x,y),意思是将x所在的堆放到y所在的堆上面. 第二种是C(x),意思是数x方块下面有多少个方块. 把两堆合成一堆,这个可以用并查集来实现,问题是,怎么样维护x方块下面有多少个方块呢? 先来分析一下题目,按照样例,我们有6个方块,1,2,3,4,5,6. 令Cnt(x) = C(x)+1. 先执行M(1,6),此时Cnt(1) = 2, Cnt(6) = 1 再

带权值并查集(转)

[POJ 1988] Cube Stacking 我们需要新增两种属性cnt[i]cnt[i]与s[i]s[i],分别表示ii之下的块数和ii所在堆的数量.在路径压缩时,cnt[i] += cnt[f[i]] ,另外在连接操作时,需要动态更新cnt[find(u)]和s[find(v)]的信息. 1 #include <iostream> 2 #define lson l,m,rt<<1 3 #define rson m+1,r,rt<<1|1 4 #define cl

P - 奔小康赚大钱 - hdu 2255(带权值的匹配)

分析:这是一个KM的模板题,也就不多说了,KM最复杂的情况都能过,下面是没有优化过的代码: ************************************************************ #include<stdio.h>#include<string.h>#include<algorithm>using namespace std; const int MAXN = 305;const int oo = 1e9+7; int w[MAXN][