题目描述:

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

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

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

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

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

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

注意:

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

思路:
首先用克鲁斯卡尔得到最小生成树,然后讲树边标记为used。用树边建图(add)。
用dfs得到每两个点之间最长的边和次长的边(严格次长)。
遍历每一个used过的边,设改边的两端为a,b。试图找到 d i s t 1 [ a ] [ b ] 或 d i s t 2 [ a ] [ b ] − w dist1[a][b]或dist2[a][b]-w dist1[a][b]或dist2[a][b]−w 最小的一组边。
为什么是dist1或dist2呢?
dist1代表的是a,b之间最长的一条边的长度,dist2代表的是a,b之间次长的一条边的长度,而且是严格次长。(都是非树边)
如果a,b之间的树边的长度小于a,b之间非树边中最长的一条边的长度,那么将该树边替换成这条非树边。
但是有一种情况就是a,b之间的树边的长度等于a,b之间非树边中最长的一条边的长度,那么此时若仍执行上述步骤,就会导致得到的新的生成树的总和和原来不变,并不是严格的次小生成树。
故此时就需要使用次长边来进行替换,这样就可以得到严格次小生成树。
缺点:
这是一种朴素做法,时间复杂度 n 2 n^2 n2,并且点的数量不能太多,否则会爆内存。进一步优化可以用到lca
代码:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e4 + 10;
int e[N], w[N], ne[N], h[N], idx = 0;
int fa[N];
int dist1[505][505],dist2[505][505];
struct Edge
{int u, v, w;bool used;bool operator< (const Edge& t) const{return w < t.w;}
}edge[N];
int find(int x)
{if (x == fa[x]){return x;}else{return fa[x] = find(fa[x]);}
}
void add(int a, int b, int c)
{e[idx] = b;w[idx] = c;ne[idx] = h[a];h[a] = idx++;
}
void dfs(int u, int Fa, int max1, int max2, int d1[], int d2[])
{d1[u] = max1;d2[u] = max2;for (int i = h[u]; i != -1; i = ne[i]){int j = e[i];if (j != Fa){int td1 = max1;int td2 = max2;if (w[i] > max1){td2 = td1;td1 = w[i];}else if (w[i] > td2 && w[i] < td1){td2 = w[i];}dfs(j, u, td1, td2, d1, d2);}}
}
int main()
{int n, m;cin >> n >> m;memset(h, -1, sizeof h);for (int i = 0; i < m; i++){int a, b, c;cin >> a >> b >> c;edge[i] = { a,b,c,false };}sort(edge, edge + m);for (int i = 0; i < 505; i++){fa[i] = i;}long long sum = 0;for (int i = 0; i < m; i++){int u = edge[i].u;int v = edge[i].v;int w = edge[i].w;int pa = find(u);int pb = find(v);if (pa != pb){fa[pa] = pb;edge[i].used = true;sum += w;add(u, v, w);add(v, u, w);}}for (int i = 1; i <= n; i++){dfs(i, -1, -1e9,-1e9,dist1[i], dist2[i]);}long long res = 1e18;for (int i = 0; i < m; i++){if (!edge[i].used){int a = edge[i].u;int b = edge[i].v;int w = edge[i].w;if (w > dist1[a][b]){res = min(res, sum - dist1[a][b] + w);}else if(w == dist1[a][b] && w > dist2[a][b]){res = min(res, sum - dist2[a][b] + w);}}}cout << res;
}

AcWing 1148. 秘密的牛奶运输相关推荐

  1. 秘密的牛奶运输 题解

    秘密的牛奶运输 农夫约翰要把他的牛奶运输到各个销售点. 运输过程中,可以先把牛奶运输到一些销售点,再由这些销售点分别运输到其他销售点. 运输的总距离越小,运输的成本也就越低. 低成本的运输是农夫约翰所 ...

  2. acwing1148——秘密的牛奶运输(求次小生成树)

    https://www.acwing.com/problem/content/description/1150/ 农夫约翰要把他的牛奶运输到各个销售点. 运输过程中,可以先把牛奶运输到一些销售点,再由 ...

  3. 【次小生成树】4.秘密的牛奶运输

    题目描述 Farmer John 要把他的牛奶运输到各个销售点.运输过程中,可以先把牛奶运输到一些销售点,再由这些销售点分别运输到其他销售点. 运输的总距离越小,运输的成本也就越低. Farmer J ...

  4. 每日算法题(Day4)----秘密的牛奶运输

    题目描述 Farmer John 要把他的牛奶运输到各个销售点.运输过程中,可以先把牛奶运输到一些销售点,再由这些销售点分别运输到其他销售点. 运输的总距离越小,运输的成本也就越低.Farmer Jo ...

  5. 算法——AcWing算法提高课中代码和题解

    文章目录 第一章 动态规划 (完成情况:64/68) 数字三角形模型 最长上升子序列模型 背包模型 状态机模型 状态压缩DP 区间DP 树形DP 数位DP 单调队列优化DP 斜率优化DP 第二章 搜索 ...

  6. 【图论专题】最小生成树的扩展应用

    整理的算法模板合集: ACM模板 最小生成树的扩展应用 能用kruskal打死不用prim kruskal是要把所有的边都遍历一遍 图论中的超级源点就比较常用,要时刻想到它 题目列表: 题目 算法 A ...

  7. 3.3.2 最小生成树的扩展应用

    回顾下最小生成树的理论基础 解释 假设选蓝色箭头的边, 再连上红色边, 因为红色边权 <= 蓝色边, 因此可以去掉蓝色边, 连接红色边, 边权之和会减小 解释 当前已经有一些连通块, 那么连通块 ...

  8. AcWing-算法提高课【合集】

    算法提高 动态规划 数字三角形 1015. 摘花生 1018.最低通行费 1027. 方格取数 最长上升子序列LIS 1017. 怪盗基德的滑翔翼 1014.登山 482.合唱队形 1012. 友好城 ...

  9. `Computer-Algorithm` 最小生成树MST,Prim,Kruskal,次小生成树

    Contents 最小生成树 Algorithm Prim Code Kruskal Prim&KruskalPrim \& KruskalPrim&Kruskal算法的性质 ...

  10. 【算法提高——第三讲(一)】图论

    来自:算法提高课 文章目录 第三章 图论 3.1 单源最短路的建图方式 3.1.1 1129. 热浪 3.1.2 1128. 信使 3.1.3 1127. 香甜的黄油 3.1.4 1126. 最小花费 ...

最新文章

  1. Qt5.12过时的类
  2. 当你女朋友第一次来你家会发生什么?
  3. Django:保持会话状态cookies和session(1)
  4. 教程-delphi的开源json库:superobject,用法简介
  5. 解析含有资源类型的字符串
  6. java中通过正则表达式提取数字
  7. matlab将数据集分成训练集和测试集,如何将数据分成训练集和测试集?
  8. oracle重建orainventory,重建oraInventory解决ORA-20001
  9. Android 下拉菜单列表客制化处理
  10. Kafka Consumer 消费逻辑
  11. EMV规范(九)——持卡人验证(CVM)三
  12. 账单php,php 处理微信账单
  13. 使用matplotlib在图片上画框框
  14. 使用roolup构建你的lib
  15. 红轴和青轴哪个手感好 红轴和青轴哪个玩游戏好
  16. Flutter播放音频
  17. 实时弹幕系统的设计与实现
  18. CentOS7 能ping通网关不能上网
  19. C语言程序设计-班级成绩管理系统
  20. 模拟电子技术基础之场效应管

热门文章

  1. python学习No6
  2. 【Python】socket同时收发与多线程防止input阻塞
  3. CQ45-307tx装windows7
  4. 从100万个数里面找出10个最大的数。写出代码并分析复杂度。
  5. html颜色代码指令,js实现的网页颜色代码表全集
  6. 理论工具之一:十字法处理问题思考
  7. 如何让公司员工认识和逐步接受OA系统
  8. IEC101平衡链路通信恢复
  9. 搜索功能分析:一个好的搜索功能有哪些结构?
  10. 近红外二区染料IRDye QC-1 NHS Ester/NHS 酯