供水管线 码蹄集

这篇具有很好参考价值的文章主要介绍了供水管线 码蹄集。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目来源:码蹄集

题目描述:

供水管线 码蹄集
供水管线 码蹄集

解决思路:

首先,题目要求我们去掉一些管道,使得总的管道管理费用最小。在去掉部分管道的情况下,城市之间不再形成一个回路,即城市之间构成了一棵树。因此,我们需要找到一棵生成树,使得所有管道管理费用之和最小。

接下来,我们需要选择合适的算法来寻找最小生成树。常用的算法有 Kruskal 算法和 Prim 算法,本题使用 Kruskal 算法实现。

Kruskal 算法的实现步骤如下:

  1. 将所有边按照管道管理费用从小到大排序;

  2. 依次枚举每条边,如果加入该边不会导致出现环,则将其加入生成树中;

  3. 当生成树的边数等于 n-1 时,停止枚举。

其中,n 表示城市的数量,生成树的边数为 n-1。

为了判断加入一条边是否会形成环,我们使用并查集维护已经加入生成树中的点的连通关系。具体地,我们让每个节点所在的集合的代表元素相同,这样就能够快速判断两个节点是否属于同一个集合。

最后,根据 Kruskal 算法得到的最小生成树,计算所有边的管理费用之和即可。

Python代码实现:

from typing import List, Tuple
import sys

class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * n

    def find(self, i):
        if self.parent[i] != i:
            self.parent[i] = self.find(self.parent[i])
        return self.parent[i]

    def union(self, i, j):
        pi, pj = self.find(i), self.find(j)
        if pi == pj:
            return False
        if self.rank[pi] < self.rank[pj]:
            pi, pj = pj, pi
        self.parent[pj], self.rank[pi] = pi, max(self.rank[pi], self.rank[pj]+1)
        return True

def min_cost(n: int, edges: List[Tuple[int, int, int]]) -> int:
    uf = UnionFind(n)
    edges.sort(key=lambda e: e[2])
    mst_cost, num_edges = 0, 0
    for u, v, w in edges:
        if uf.union(u-1, v-1):
            mst_cost += w
            num_edges += 1
            if num_edges == n - 1:
                break
    return mst_cost

n, k = map(int, sys.stdin.readline().rstrip().split())
edges = [tuple(map(int, sys.stdin.readline().rstrip().split())) for _ in range(k)]
sys.stdout.write(str(min_cost(n, edges)))

C++代码实现:

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

struct Edge{
    int from, to, cost;
    bool operator<(const Edge& e)const{
        return cost < e.cost;
    }
};

class UnionFind{
    vector<int> parent, rank;

public:
    UnionFind(int n){
        parent.resize(n);
        rank.resize(n, 0);
        for(int i=0; i<n; ++i)
            parent[i] = i;
    }

    int find(int i){
        if(parent[i] != i)
            parent[i] = find(parent[i]);
        return parent[i];
    }

    bool union_sets(int i, int j){
        int pi = find(i);
        int pj = find(j);
        if(pi == pj)
            return false;
        if(rank[pi] < rank[pj])
            swap(pi, pj);
        parent[pj] = pi;
        rank[pi] = max(rank[pi], rank[pj]+1);
        return true;
    }
};

int main(){
    int n, k;
    cin >> n >> k;

    vector<Edge> edges(k);
    for(int i=0; i<k; ++i){
        cin >> edges[i].from >> edges[i].to >> edges[i].cost;
        edges[i].from--;
        edges[i].to--;
    }
    sort(edges.begin(), edges.end());

    UnionFind uf(n);
    int mstCost = 0, numEdges = 0;
    for(Edge e: edges){
        if(uf.union_sets(e.from, e.to)){
            mstCost += e.cost;
            numEdges++;
            if(numEdges == n-1)
                break;
        }
    }

    cout << mstCost << endl;

    return 0;
}

Java代码实现:

import java.util.*;

class Edge implements Comparable<Edge>{
    int from, to, cost;

    public Edge(int from, int to, int cost){
        this.from = from;
        this.to = to;
        this.cost = cost;
    }

    @Override
    public int compareTo(Edge e){
        return this.cost - e.cost;
    }
}

class UnionFind{
    int[] parent;
    int[] rank;

    public UnionFind(int n){
        parent = new int[n];
        rank = new int[n];
        for(int i=0; i<n; ++i)
            parent[i] = i;
    }

    public int find(int i){
        if(parent[i] != i)
            parent[i] = find(parent[i]);
        return parent[i];
    }

    public boolean union(int i, int j){
        int pi = find(i);
        int pj = find(j);
        if(pi == pj)
            return false;
        if(rank[pi] < rank[pj]){
            int temp = pi;
            pi = pj;
            pj = temp;
        }
        parent[pj] = pi;
        rank[pi] = Math.max(rank[pi], rank[pj]+1);
        return true;
    }
}

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int n = scanner.nextInt();
        int k = scanner.nextInt();

        UnionFind uf = new UnionFind(n);
        List<Edge> edges = new ArrayList<>();
        for(int i=0; i<k; ++i){
            int u = scanner.nextInt()-1;
            int v = scanner.nextInt()-1;
            int w = scanner.nextInt();
            edges.add(new Edge(u, v, w));
        }
        Collections.sort(edges);

        int mstCost = 0, numEdges = 0;
        for(Edge e: edges){
            if(uf.union(e.from, e.to)){
                mstCost += e.cost;
                numEdges++;
                if(numEdges == n-1)
                    break;
            }
        }

        System.out.println(mstCost);
    }
}

代码提交测试结果:

供水管线 码蹄集

附B站老师讲解链接,可供参考:https://www.bilibili.com/video/BV1cs4y137za/?t=551.4文章来源地址https://www.toymoban.com/news/detail-464143.html

到了这里,关于供水管线 码蹄集的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法竞赛入门【码蹄集进阶塔335题】(MT2301-2305)

    为什么突然想学算法了? 用较为“官方”的语言讲 ,是因为算法对计算机科学的所有分支都非常重要。 在绝大多数的计算机科学分支领域中,要想完成任何实质性的工作,理解算法的基础知识并掌握与算法密切相关的数据结构知识是必不可少的。 但从实际而言 ,是因为当

    2024年02月06日
    浏览(48)
  • 算法竞赛入门【码蹄集进阶塔335题】(MT2051-2075)

    为什么突然想学算法了? 用较为“官方”的语言讲 ,是因为算法对计算机科学的所有分支都非常重要。 在绝大多数的计算机科学分支领域中,要想完成任何实质性的工作,理解算法的基础知识并掌握与算法密切相关的数据结构知识是必不可少的。 但从实际而言 ,是因为当

    2023年04月15日
    浏览(42)
  • 算法竞赛入门【码蹄集进阶塔335题】(MT2126-2150)

    为什么突然想学算法了? 用较为“官方”的语言讲 ,是因为算法对计算机科学的所有分支都非常重要。 在绝大多数的计算机科学分支领域中,要想完成任何实质性的工作,理解算法的基础知识并掌握与算法密切相关的数据结构知识是必不可少的。 但从实际而言 ,是因为当

    2023年04月19日
    浏览(35)
  • 算法竞赛入门【码蹄集进阶塔335题】(MT2271-2275)

    为什么突然想学算法了? 用较为“官方”的语言讲 ,是因为算法对计算机科学的所有分支都非常重要。 在绝大多数的计算机科学分支领域中,要想完成任何实质性的工作,理解算法的基础知识并掌握与算法密切相关的数据结构知识是必不可少的。 但从实际而言 ,是因为当

    2024年02月07日
    浏览(31)
  • 算法竞赛入门【码蹄集进阶塔335题】(MT2226-2250)

    为什么突然想学算法了? 用较为“官方”的语言讲 ,是因为算法对计算机科学的所有分支都非常重要。 在绝大多数的计算机科学分支领域中,要想完成任何实质性的工作,理解算法的基础知识并掌握与算法密切相关的数据结构知识是必不可少的。 但从实际而言 ,是因为当

    2024年02月11日
    浏览(34)
  • 算法竞赛入门【码蹄集进阶塔335题】(MT2201-2225)

    为什么突然想学算法了? 用较为“官方”的语言讲 ,是因为算法对计算机科学的所有分支都非常重要。 在绝大多数的计算机科学分支领域中,要想完成任何实质性的工作,理解算法的基础知识并掌握与算法密切相关的数据结构知识是必不可少的。 但从实际而言 ,是因为当

    2024年02月08日
    浏览(31)
  • 算法竞赛入门【码蹄集进阶塔335题】(MT2291-2295)

    为什么突然想学算法了? 用较为“官方”的语言讲 ,是因为算法对计算机科学的所有分支都非常重要。 在绝大多数的计算机科学分支领域中,要想完成任何实质性的工作,理解算法的基础知识并掌握与算法密切相关的数据结构知识是必不可少的。 但从实际而言 ,是因为当

    2024年02月06日
    浏览(31)
  • 算法竞赛入门【码蹄集新手村600题】(MT1020-1040)

    码蹄集网站地址:https://www.matiji.net/exam/ojquestionlist (1)题目 输入一个实数,第一次按实型输出;第二次保留2位小数输出;第三次保留3位小数但最小列宽8列输出,空格分隔。 格式 样例1 (2)参考代码 (1)题目 输出3.1415926、12345678.123456789的小数、指数形式。 格式 样例1 (

    2024年02月16日
    浏览(42)
  • 算法竞赛入门【码蹄集进阶塔335题】(MT2151-2175)

    为什么突然想学算法了? 用较为“官方”的语言讲 ,是因为算法对计算机科学的所有分支都非常重要。 在绝大多数的计算机科学分支领域中,要想完成任何实质性的工作,理解算法的基础知识并掌握与算法密切相关的数据结构知识是必不可少的。 但从实际而言 ,是因为当

    2024年02月02日
    浏览(50)
  • 算法竞赛入门【码蹄集新手村600题】(MT1280-1300)C语言

    码蹄集网站地址:https://www.matiji.net/exam/ojquestionlist (1)题目 输入正整数N(1500),首先计算其逆序数M(比如12逆序后是21)。然后输出N的M次方的最后3位数。 格式 样例1 (2)参考代码 (1)题目 一个自然数,如果每一位数的位数次幂之和等于该自然数,则称之为Disarium数。 比如

    2024年02月07日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包