题目描述

给出无向图中M个节点间N条边的权值。
求一个使得所有点连通的子图,要求图内的边权和最小

Input

测试输入包含若干测试用例
每个测试用例的第1行包含N、M ( <100 )
随后的 N 行每行包含3个数,边的起点,终点,权值
节点从1到M编号
当N为0时,全部测试结束.

Output

对每个测试用例,在1行里输出最小生成树权值。
若不存在符合要求的子图,则输出“?”。

Sample Input

3 3
1 2 1
1 3 2
2 3 4
1 3
2 3 2
0 100

Sample Output

3
?

kruskal算法
定理:任意一个最小生成树一定包含无向图中权值最小的那一条边。
所以给定一张无向图G = (V, E),n = V, m = E,先选出k条边构成一个生成森林,再从剩余的m-k条边中选出n - 1 - k添加到森林中,并且选出的边的权值之和最小.
kruskal算法从剩余的边中选出权值最小的,加入到森林中,图中节点的联通情况可用并查集维护

kruskal算法流程:
1.建立并查集,每个点各自构成一个集合
2.把所有的边按照权值从小到大排序,一次扫描每一条边
3.若x,y属于同一个集合,则忽略这条边,继续扫描下一条边
4.否则,合并x,y所在的集合,并将z累加到答案中

时间复杂度:O(m log(m)).
代码如下:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int f[200005];
struct p{int x, y, z;
}arr[200005];
bool cmp(p a, p b)
{return a.z < b.z;
}
int Find(int x)
{if(x != f[x])f[x] = Find(f[x]);return f[x];
}
int main()
{int n, m;cin >> n >> m;for(int i = 1; i <= n; i++)f[i] = i;for(int i = 0; i < m; i++){cin >> arr[i].x >> arr[i].y >> arr[i].z;}sort(arr, arr + m, cmp);int ans = 0, sum = 0;for(int i = 0; i < m; i++){int x = Find(arr[i].x);int y = Find(arr[i].y);if(x == y)continue;f[x] = y;sum++;ans += arr[i].z;if(sum == n - 1)break;}cout << ans << endl;return 0;
}

prim算法
Prim算法的思想是:取图中任意一点作为起点放入树中,并向邻近树的点不断延伸,每次延伸的点要求满足到树的距离最短。

代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>
#define Maxn 0x3f3f3f3f
using namespace std;
int arr[105][105];
int dis[105];  //记录每个结点间的最短距离
bool vis[105];  //判断该点是否被选过
int n ,m, ans;
void prim()
{memset(vis, false, sizeof vis);for(int i = 0; i <= n; i++)dis[i] = arr[1][i];dis[1] = 0;vis[1] = true;for(int i = 1; i < n; i++){int x = 0;for(int j = 1; j <= n; j++){if(!vis[j] && dis[j] < dis[x]){x = j;}}if(!x){cout << "?" << endl;return ;}vis[x] = true;ans += dis[x];for(int i = 1; i <= n; i++)if(!vis[i])dis[i] = min(dis[i], arr[x][i]);}cout << ans << endl;
}
int main()
{while(cin >> m >> n &&m){for(int i = 0; i <= n; i++)for(int j = 0; j <= n; j++)arr[i][j] = i == j? 0 : Maxn;int a, b, c;for(int i = 1; i <= m; i++){cin >> a >> b >> c;arr[a][b] = arr[b][a] = min(arr[a][b], c);}ans = 0;prim();}return 0;
}

prim算法之二叉堆优化,时间复杂度:O(m log(n))
代码如下:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int arr[105][105];
int dis[105];
bool vis[105];
typedef pair<int ,int > p;
int main()
{int n, m;while(cin >> m >> n && m){for(int i = 0; i <= n; i++)for(int j = 0; j <= n; j++)arr[i][j] = i == j ? 0 : INF;memset(dis, INF, sizeof dis);memset(vis, false, sizeof vis);int a, b, c;for(int i = 0; i < m; i++){cin >> a >> b >> c;arr[a][b] = arr[b][a] = min(arr[a][b], c);}priority_queue<p, vector<p>, greater<p> > q;dis[1] = 0;int ans = 0, sum = 0;q.push({0, 1});while(q.size()){p cur = q.top();q.pop();int u = cur.second;if(vis[u])continue;vis[u] = true;sum++;ans += dis[u];for(int i = 1; i <= n; i++){if(!vis[i] && dis[i] > arr[u][i]){dis[i] = arr[u][i];q.push({dis[i], i});}}}if(sum == n)cout << ans << endl;  //判断是否连通else cout << "?" << endl;}return 0;
}

畅通工程(最小生成树模板)相关推荐

  1. HDU 1863畅通工程(最小生成树)(prim算法)

    畅通工程 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  2. hdu1879 继续畅通工程 最小生成树

    继续畅通工程 此题明显属于最小生成树的题目 关于最小生成树,有两种方法,一种是Kruskal方法,一种是Prim算法,第一种用并查集即可实现 1 /* 2 hdu1879 3 2013-03-18 1 ...

  3. hdu 1233 还是畅通工程 最小生成树(prim算法 + kruskal算法)

    还是畅通工程                                                                            Time Limit: 4000/2 ...

  4. hdu 1879 继续畅通工程 (最小生成树)

    继续畅通工程 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  5. HDU 1879 继续畅通工程 最小生成树

    继续畅通工程 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description ...

  6. 还是畅通工程 最小生成树

    某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可 ...

  7. 畅通工程//最小生成树prim

    题目: 畅通工程 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...

  8. hdu 1879 继续畅通工程 最小生成树

    继续畅通工程                                                                             Time Limit: 2000/ ...

  9. 题目1017:还是畅通工程(最小生成树初步应用)

    题目链接:http://ac.jobdu.com/problem.php?pid=1017 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...

  10. HDU 1863 畅通工程 最小生成树

    思路: 比较典型的最小生成树的题目了..在这里用求最小生成树的经典算法K(Kruskal)算法和P(Prim)算法.我的 K 算法用的是结构体来存图,P 算法用的是邻接矩阵来存图,K算法的复杂度是O( ...

最新文章

  1. 总结—elasticsearch启动失败的几种情况及解决
  2. SSM+BJUI实现CRUD的报表功能
  3. javascript数组的属性、方法和清空-最全!!!(必看)
  4. python的if语句例句_Python入门之if条件语句
  5. Activiti6记录
  6. Matlab调用Python函数,出现OSError: [WinError 126] 找不到指定的模块报错
  7. 图扑智慧交通:数字化地铁大屏管控运维平台
  8. 一个 Gitlab 帐号无法访问文件、克隆项目问题的解决
  9. On the Opportunities and Risks of Foundation Models- APPLICATIONS
  10. VMware虚拟机+Kali linux 2021.2 下载和安装以及初始操作
  11. 几何基础 罗德里格公式
  12. 【算法详解】splay的初步了解
  13. Cesium交流群链接
  14. 汽车之家搜索算法工程师招聘
  15. 《软技能-代码之外的生存指南》读书笔记
  16. Android 雷达图(蜘蛛网状图)
  17. Python3[爬虫实战] scrapy爬取汽车之家全站链接存json文件
  18. 防火墙导致web访问不到服务器解决方法
  19. TOOM舆情分析网络舆情监控平台研究现状
  20. Java项目:jsp房地产客户关系管理系统

热门文章

  1. mysql数据库主从复制部署笔记
  2. fltk在UbuntuLinux中搭建和测试-《C++程序设计原理与实践》Chapter12:显示模型 环境构建...
  3. OpenCV 离散傅里叶变换
  4. [Swift]LeetCode70. 爬楼梯 | Climbing Stairs
  5. EF中使用SQL语句或存储过程
  6. 第三周PLECS仿真实验
  7. 如何解决软键盘弹出引起的各种不适
  8. java 线程间的通讯(升级版)
  9. WinForm 的dataGridView全选,反选
  10. 深度学习入门读书笔记—全