1148. 秘密的牛奶运输 (次小生成树)

1148. 秘密的牛奶运输 - AcWing题库

农夫约翰要把他的牛奶运输到各个销售点。

运输过程中,可以先把牛奶运输到一些销售点,再由这些销售点分别运输到其他销售点。

运输的总距离越小,运输的成本也就越低。

低成本的运输是农夫约翰所希望的。

不过,他并不想让他的竞争对手知道他具体的运输方案,所以他希望采用费用第二小的运输方案而不是最小的。

现在请你帮忙找到该运输方案。

注意:

  • 如果两个方案至少有一条边不同,则我们认为是不同方案;
  • 费用第二小的方案在数值上一定要严格大于费用最小的方案;
  • 答案保证一定有解;
输入格式

第一行是两个整数 N,M,表示销售点数和交通线路数;

接下来 M 行每行 3 个整数 x,y,z,表示销售点 x 和销售点 y 之间存在线路,长度为 z。

输出格式

输出费用第二小的运输方案的运输总距离。

数据范围

1≤N≤500,
1≤M≤104,
1≤z≤109,
数据中可能包含重边。

输入样例:
4 4
1 2 100
2 4 200
2 3 250
3 4 100
输出样例:
450

解析: 

题目要求求一棵次小生成树。

具体操作:

1.求最小生成树,统计标记每条边时树边,还是非树边;同时把最小生成树建出来。

2.预处理最小生成树上任意两点间的边权最大值dist[a][b]

3.依次枚举所有非树边,求min(sum+w-dist[a][b]),满足w>dist[a][b]。

O(mlogm+n^2)

为什么要求出次大距离,只求最大距离不可以吗?

在算法中,求解每个点到其它点的最大距离和次大距离的目的是为了在后续遍历不在最小生成树中的边时,能够利用这些信息进行计算,找到替换权值最小的边。

具体来说,对于一条边 (a, b, w),假设 a 和 b 已经在最小生成树中,而当前边 (a, b, w) 不在最小生成树中。我们可以分两种情况讨论:

1. 如果 w 大于 a 到 b 的最大距离,那么替换后的生成树权值为当前生成树的总权值加上 w 减去 a 到 b 的最大距离,因为 w 大于最大距离,所以替换后生成树的总权值会减小。

2. 如果 w 大于 a 到 b 的次大距离,那么替换后的生成树权值为当前生成树的总权值加上 w 减去 a 到 b 的次大距离,同样因为 w 大于次大距离,所以替换后生成树的总权值会减小。

所以,为了确保找到替换权值最小的边,需要同时计算每个点到其它点的最大距离和次大距离。这样在遍历不在最小生成树中的边时,可以根据这些信息选择合适的边进行替换,以得到次小生成树的权值。

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
#include<sstream>
#include<deque>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N = 505, M = 2e4 + 5;
int n, m;
struct Edge {int a, b, c;bool f;bool operator<(const Edge& t)const {return c < t.c;}
}edge[M];
int dist1[N][N], dist2[N][N];
int fa[N];
int h[N], e[M], w[M], ne[M], idx;void add(int a, int b, int c) {e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}int find(int a) {if (fa[a] == a)return a;return fa[a] = find(fa[a]);
}void dfs(int u, int f, int mx1, int mx2, int d1[], int d2[]) {d1[u] = mx1, d2[u] = mx2;for (int i = h[u]; i != -1; i = ne[i]) {int j = e[i];if (j != f) {int t1 = mx1, t2 = mx2;if (mx1 < w[i]) {t2 = t1, t1 = w[i];}else if (mx2 < w[i] && w[i] < mx1) {t2 = w[i];}dfs(j, u, t1, t2, d1, d2);}}
}int main() {cin >> n >> m;memset(h, -1, sizeof h);for (int i = 1, a, b, c; i <= m; i++) {scanf("%d%d%d", &a, &b, &c);edge[i] = { a,b,c };}for (int i = 1; i <= n; i++) fa[i] = i;sort(edge + 1, edge + 1 + m);LL sum = 0;for (int i = 1; i <= m; i++) {int a = edge[i].a, b = edge[i].b, c = edge[i].c;int pa = find(edge[i].a), pb = find(edge[i].b);if (pa != pb) {sum += c;fa[pa] = pb;add(a, b, c), add(b, a, c);edge[i].f = 1;}}for (int i = 1; i <= n; i++) dfs(i, -1, -1e9, -1e9, dist1[i], dist2[i]);LL ret = 1e18;for (int i = 1; i <= m; i++) {if (!edge[i].f) {int a = edge[i].a, b = edge[i].b, c = edge[i].c;LL t;if (c > dist1[a][b]) {t = sum + c - dist1[a][b];}else if (c > dist2[a][b]) {t = sum + c - dist2[a][b];}ret = min(ret, t);}}cout << ret << endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/641123.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

知识笔记(九十六)———在vue中使用echarts

1、安装 npm install echarts --save 2、在vue中引入&#xff08;全局引入&#xff09; // 引入echarts import echarts from echarts Vue.prototype.$echarts echarts3、在vue中的使用 需要用到echart的地方先设置一个div的id、宽高 提示&#xff1a; 可以在一个页面中引…

数据结构之使用顺序表写出通讯录

前言 昨天我们踏入了数据结构的深山&#xff0c;并且和顺序表battle了一番&#xff0c;虽说最后赢了&#xff0c;但同时也留下了一个问题&#xff1a;如何从顺序表的增删查改加强到通讯录的的增删查改&#xff0c;别急&#xff0c;今天就带你一探究竟。 一.回顾与思考 我们昨…

geemap学习笔记053:纹理特征

前言 纹理特征通常描述了遥感影像中像素之间的空间关系和变化&#xff0c;对于地物分类、目标检测以及图像分割等遥感应用非常有价值。本节将会介绍Earth Engine中提供的一些纹理特征计算方法&#xff0c;包括熵和灰度共生矩阵。 1 导入库并显示数据 import ee import geema…

【UE5】第一次尝试项目转插件(Plugin)的时候,无法编译

VS显示100条左右的错误&#xff0c;UE热编译也不能通过。原因可能是[名字.Build.cs]文件的错误&#xff0c;缺少一些内容&#xff0c;比如说如果要写UserWidget类&#xff0c;那么就要在 ]名字.Build.cs] 中加入如下内容&#xff1a; public class beibaoxitong : ModuleRules …

自己本机Video retalking制作数字人

首先需要注意的是&#xff0c;这个要求你的笔记本显存和内存都比较大。我的电脑内存是64G&#xff0c;显卡是8G&#xff0c;操作系统是Windows 11&#xff0c;勉强能够运行出来&#xff0c;但是效果不是很好。 效果如下&#xff0c;无法上传视频&#xff0c;只能通过图片展示出…

[分章:阅读]《我的第一本算法书》

第一章数据结构 1.链表 1、数据结构之一&#xff0c;线性排列数据&#xff0c;指针链接数据&#xff1b;访问O&#xff08;n&#xff09;&#xff0c;删除/添加O&#xff08;1&#xff09; 2、类似链条。 2.数组 1、线性排列数据&#xff0c;含数据下标&#xff08;即索引&…

C++如何在0和1之间取随机数

在C中&#xff0c;你可以使用 <random> 库来生成0和1之间的随机数。这个库提供了各种生成随机数的方法&#xff0c;包括均匀分布的随机数。 下面是一个简单的例子&#xff0c;展示如何使用 <random> 库来生成0和1之间的随机数&#xff1a; cpp复制代码 #include…

二、docker的常用命令(持续补充img)

目录 一、启动相关1.设置容器开机启动 二、查询相关1.查询所有容器&#xff08;包括停止的&#xff09; 三、修改相关1.指定容器开机自启动 一、启动相关 1.设置容器开机启动 在我们使用镜像run一个容器的时候&#xff0c;希望这个容器随着docker的启动而启动&#xff08;我的…

Ubuntu20.04.3LTS桌面版与Window10双系统并存

Ubuntu20.04.3LTS桌面版与Window10双系统并存 文章目录 Ubuntu20.04.3LTS桌面版与Window10双系统并存1.分区与安装1. 硬盘分区1. 一般用途2. 服务器用 2. 操作系统版本及分区信息3. 安装时创建用户4. 安装后修改root设置用户密码&#xff1a;3. 安装时指定ip4. 设置静态IP 2. 安…

【leetcode100-051到054】【图论】四题合集

【岛屿数量】 给你一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。 岛屿总是被水包围&#xff0c;并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外&#xff0c;你可以假设…

Java线程池七大参数详解和配置(面试重点)

一、corePoolSize核心线程数 二、maximunPoolSize最大线程数 三、keepAliveTime空闲线程存活时间 四、unit空闲线程存活时间的单位 五、workQueue线程工作队列 1、ArrayBlockingQueue FIFO有界阻塞队列 2、LinkedBlockingQueue FIFO无限队列 3、PriorityBlockingQueue V…

【代码随想录】刷题笔记Day54

前言 差单调栈就结束代码随想录一刷啦&#xff0c;回家二刷打算改用python补充进博客&#xff0c;小涛加油&#xff01;&#xff01;&#xff01; 647. 回文子串 - 力扣&#xff08;LeetCode&#xff09; 双指针法 中心点外扩&#xff0c;注意中心点可能有一个元素可能有两个…

neo4j jdk17下 dump 报错

更换jdk版本 只需要改下bin目录下的neo4j.bat, 把set "JAVA_HOMEXXXX"加入进去就行 windows SET "JAVA_HOMEc:\...." linux bin目录下 neo4j 在首行添加JAVA_HOME/usr/local/jdk文件夹即可 tomcat 指定jdk 找到bin下的setclasspath.bat文件&#xff1b;在…

Supervised Contrastive 损失函数详解

有什么不对的及时指出&#xff0c;共同学习进步。(●’◡’●) 有监督对比学习将自监督批量对比方法扩展到完全监督设置&#xff0c;能够有效地利用标签信息。属于同一类的点簇在嵌入空间中被拉到一起&#xff0c;同时将来自不同类的样本簇推开。这种损失显示出对自然损坏很稳…

【Linux C | 进程】进程终止、等待 | exit、_exit、wait、waitpid

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

【Kafka】开发实战和Springboot集成kafka

目录 消息的发送与接收生产者消费者 SpringBoot 集成kafka服务端参数配置 消息的发送与接收 生产者 生产者主要的对象有&#xff1a; KafkaProducer &#xff0c; ProducerRecord 。 其中 KafkaProducer 是用于发送消息的类&#xff0c; ProducerRecord 类用于封装Kafka的消息…

C 练习实例39

题目&#xff1a;有一个已经排好序的数组。现输入一个数&#xff0c;要求按原来的规律将它插入数组中。 代码&#xff1a; #include <stdio.h> #define N 10 int main() {int a[N]{1,3,5,7,9,11,13,15,17}; //元素数组int nN;int i,temp;printf("原始数组是:\n&qu…

仅使用K-M法+Cox比例风险模型就能发二区文章 | SEER公共数据库周报(1.17)

欢迎各位参加本周中山大学著名卫生统计学家方积乾教授公益直播讲座&#xff01; 就在本周三晚&#xff0c;主题为“真实世界研究与RCT研究”&#xff0c;欢迎各位预约参加&#xff01; SEER&#xff08;The Surveillance, Epidemiology, and End Results&#xff09;数据库是由…

回溯算法篇-01:全排列

力扣46&#xff1a;全排列 题目分析 这道题属于上一篇——“回溯算法解题框架与思路”中的 “元素不重复不可复用” 那一类中的 排列类问题。 我们来回顾一下当时是怎么说的&#xff1a; 排列和组合的区别在于&#xff0c;排列对“顺序”有要求。比如 [1,2] 和 [2,1] 是两个不…

【AI】深度学习在编码中的应用(10)

目录 先看2个定义&#xff1a;P帧和B帧 基于层次学习的高效视频压缩技术 基于B帧的B-EPIC方法 今天来学习编码配置优化技术。 先看2个定义&#xff1a;P帧和B帧 在视频压缩中&#xff0c;P帧和B帧都是关键的概念&#xff0c;它们与I帧一起构成了视频压缩的三种基本帧类型。…