POJ3723(邻接表+并查集+Kruskal)

题目链接:点击打开链接

解题思路:

根据相互之间的关系,可以转化一个无向图中最大权森林的问题。也就是把边权取反,然后用最小生成树求解。

本题用邻接表存储,Kruskal求最小生成树。

完整代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <climits>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn = 500001;

struct edge
{
    int u , v , cost;
};

int n , m , r;
int x[maxn] , y[maxn] , d[maxn];

bool cmp(const edge &e1 , const edge &e2)
{
    return e1.cost < e2.cost;
}

edge es[maxn];
int V , E;

int f[maxn] , rank[maxn];

void init_union_find(int cnt)
{
    for(int i = 0 ; i <= cnt ; i ++)
    {
        f[i] = i;
        rank[i] = 0;
    }
}

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

void unite(int x , int y)
{
    x = find(x);
    y = find(y);
    if(x != y)
    {
        if(rank[x] < rank[y])
        {
            f[x] = y;
        }
        else
        {
            f[y] = x;
            if(rank[x] == rank[y])
                rank[x] ++;
        }
    }
}

bool same(int x , int y)
{
    return find(x) == find(y);
}

int kruskal()
{
    sort(es , es + E , cmp);
    init_union_find(V);
    int res = 0;
    for(int i = 0 ; i < E ; i ++)
    {
        edge e = es[i];
        if(!same(e.u , e.v))
        {
            unite(e.u , e.v);
            res += e.cost;
        }
    }
    return res;
}

void solve()
{
    V = n + m;
    E = r;
    for(int i = 0 ; i < r ; i ++)
    {
        es[i] = (edge){ x[i] , n + y[i] , -d[i] };
    }
    LL res = 10000 * (n + m) + kruskal();
    printf("%lld\n" , res);
}

int main()
{

    #ifdef DoubleQ
    freopen("in.txt" , "r" , stdin);
    #endif
    int T;
    cin >> T;
    while(T--)
    {
        //cin >> n >> m >> r;
        scanf("%d%d%d" , &n , &m , &r);
        for(int i = 0 ; i < r ; i ++)
        {
            //cin >> x[i] >> y[i] >> d[i];
            scanf("%d%d%d" , &x[i] , &y[i] , &d[i]);
        }
        solve();
    }
    return 0;
}

更多精彩请访问:点击打开链接

时间: 2024-10-12 02:11:19

POJ3723(邻接表+并查集+Kruskal)的相关文章

赛码&quot;BestCoder&quot;杯中国大学生程序设计冠军赛1009——邻接表+并查集——Exploration

Problem Description Miceren likes exploration and he found a huge labyrinth underground! This labyrinth has N caves and some tunnels connecting some pairs of caves. There are two types of tunnel, one type of them can be passed in only one direction a

HDU 3371 Connect the Cities(并查集+Kruskal)

题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=3371 思路: 这道题很明显是一道最小生成树的题目,有点意思的是,它事先已经让几个点联通了.正是因为它先联通了几个点,所以为了判断连通性 很容易想到用并查集+kruskal. 不过要注意 这题有一个坑点,就是边数很多 上限是25000,排序的话可能就超时了.而点数则比较少 上限是500,所以很多人选择用Prim做.但我个人觉得这样连通性不好判断.其实边数多没关系,我们主要去重就好啦,用邻接矩阵存下两点

SQL Server利用RowNumber()内置函数与Over关键字实现通用分页存储过程(支持单表或多表结查集分页)

原文:SQL Server利用RowNumber()内置函数与Over关键字实现通用分页存储过程(支持单表或多表结查集分页) SQL Server利用RowNumber()内置函数与Over关键字实现通用分页存储过程,支持单表或多表结查集分页,存储过程如下: /******************/ --Author:梦在旅途(www.Zuowenjun.cn) --CreateDate:2015-06-02 --Function:分页获取数据 /******************/ crea

【BZOJ-4569】萌萌哒 ST表 + 并查集

4569: [Scoi2016]萌萌哒 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 459  Solved: 209[Submit][Status][Discuss] Description 一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条件表示为四个数,l1,r1,l2,r2,即两个长度相同的区间,表示子串Sl1Sl1+1Sl1+2...Sr1与Sl2Sl2+1Sl2+2.

HDU 1863 并查集+Kruskal

点击打开链接 题意:不解释了 思路:也不解释了,并查集判段连通性,Kruskal求最小生成树,大水题(/ □ \) #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; typedef unsigned long lo

POJ 1797 Heavy Transportation(二分+并查集/kruskal)

Heavy Transportation Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 24398   Accepted: 6472 Description Background Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now expand business. But he needs a clever man

[HDU3710] Battle Over Cities [树链剖分+线段树+并查集+kruskal+思维]

题面 一句话题意: 给定一张 N 个点, M 条边的无向连通图, 每条边上有边权 w . 求删去任意一个点后的最小生成树的边权之和. 思路 首先肯定要$kruskal$一下 考虑$MST$里面去掉一个点,得到一堆联通块,我们要做的就是用原图中剩下的边把这些联通块穿起来 考虑这个点$u$在$MST$上的位置,可以知道有两种边:一种是从$u$的任意一个儿子的子树连到$u$的子树外面的,一种是在$u$的两个儿子的子树之间连接的 第一种情况: 考虑边$(u,v)$,没有进入$MST$中,那么若它是某个节

hdu1875 畅通工程再续 并查集+kruskal最小生成树

Problem Description 相信大家都听说一个"百岛湖"的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现.现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后,决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米.当然,为了节省资金,只要求实现任意2个小岛之间有路通即可.其中桥的价格为 100元/米.

BZOJ 4569 [Scoi2016]萌萌哒 ——ST表 并查集

好题. ST表又叫做稀疏表,这里利用了他的性质. 显然每一个条件可以分成n个条件,显然过不了. 然后发现有许多状态是重复的,首先考虑线段树,没什么卵用. 然后ST表,可以每一层表示对应的区间大小的两个部分是否合并,如果合并就不向下递归. 然后可以剪去许多状态,变成了$O(nlogn)$的. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using n