DS-7.1实现求最小生成树的克鲁斯卡尔算法(并查集实现)
来源:互联网 发布:印度现状 知乎 编辑:程序博客网 时间:2024/05/18 09:45
写在前面:首先吐槽一下学校的OJ,题目上说是输入字母结果后台测试样例却出现数字= =!害得我改来改去提交了7次都是错的。(呸
回到正题
题目描述
已知有权无向图G,利用克鲁斯卡尔算法求出该图的最小生成树。
输入
第一行输入两个正整数n和m(空格间隔), 分别表示图G的顶点总数和边的总数。
第二行连续输入n个字母,分别表示n个顶点的信息。
第三行连续输入m条边的信息,每条边的输入格式为(v1,v2,w),表示一条关联顶点v1和v2的边,其权值为w。
输出
按边上权值由小到大的顺序依次输出各个边。
输出边的时,若该边被选中,则在该边信息之后输出1,否则输出0。
例如:
(v1,v2,w,1) 表示与顶点v1和v2相关联的边,权值为w,被选中。
(v1,v2,w,0) 表示与顶点v1和v2相关联的边,权值为w,未被选中。
解题思路
看到这道题,就是想到用邻接矩阵来存储,然后将题目信息依次输入。克鲁斯卡尔算法是将权重排序,然后从最小的开始取,如果不构成环就将边加入,如果构成环就舍弃,也就是题目中说的1和0。最主要的问题就是我们要不停的检查是否构成环,其实这里应该可以用DFS来判断连通分量(不会所以放弃了)。所以就采用了前几天在博客上看到的并查集。
并查集由一个整数型的数组和两个函数构成。数组pre[]记录了每个点的前导点是什么,函数find是查找,join是合并(这道题没有用到)。
int Find(int *parent, int f) { while (parent[f] > 0) { f = parent[f]; } return f;}
我们很容易通过并查集来判断这些点是否都在一个集合里,如果在的话就将边舍弃,如果不在的话就放入。
刚学并查集,理解还不是很深刻,日后再补啦!
下面贴上本题代码
#include <iostream>#include <cstring>using namespace std;#define MAXNUM 50typedef struct { int vexnum; int arcsnum; char vertext[MAXNUM]; int arcs[MAXNUM][MAXNUM];} AdjMartix;typedef struct { int begin; int end; int weight;} Edge;using namespace std;AdjMartix *CreatAdjMartix(AdjMartix *G) { G = (AdjMartix *) malloc(sizeof(AdjMartix)); memset(G->arcs, 0, sizeof(G->arcs)); cin >> G->vexnum >> G->arcsnum; char ch1, ch2, a, b, c, d; int w; for (int i = 0; i < G->vexnum; i++) { cin >> G->vertext[i]; } for (int i = 0; i < G->arcsnum; i++) { cin >> a >> ch1 >> b >> ch2 >> c >> w >> d; if(ch1>='0'&&ch1<='9'&&ch2>='0'&&ch2<='9'){ G->arcs[ch1-'0'][ch2-'0']=w; } else{ G->arcs[ch1 - 'A' + 1][ch2 - 'A' + 1] = w; } } for(int i = 0; i < G->vexnum; i++) { for(int j = i; j < G->vexnum; j++) { G->arcs[j][i] =G->arcs[i][j]; } } return G;}int cmp(const void *a, const void *b) { return (*(Edge *) a).weight - (*(Edge *) b).weight;}int Find(int *parent, int f) { while (parent[f] > 0) { f = parent[f]; } return f;}void MiniSpanTree_Kruskal(AdjMartix *G) { int parents[MAXNUM]; Edge edge[MAXNUM]; int k = 0; int n, m; for (int i = 0; i < G->arcsnum - 1; i++) { for (int j = i + 1; j < G->arcsnum; j++) { if (G->arcs[i][j]) { edge[k].begin = i; edge[k].end = j; edge[k].weight = G->arcs[i][j]; k++; } } } qsort(edge, G->arcsnum, sizeof(Edge), cmp); memset(parents, 0, sizeof(parents)); for (int i = 0; i < G->arcsnum; i++) { n = Find(parents, edge[i].begin); m = Find(parents, edge[i].end); if (n != m) { parents[n] = m; cout << "(" << G->vertext[edge[i].begin - 1] << "," << G->vertext[edge[i].end - 1] << "," << edge[i].weight << "," << 1 << ")"; } if (n == m) { cout << "(" << G->vertext[edge[i].begin - 1] << "," << G->vertext[edge[i].end - 1] << "," << edge[i].weight << "," << 0 << ")"; } }}int main() { AdjMartix *adjMartix; adjMartix = CreatAdjMartix(adjMartix); MiniSpanTree_Kruskal(adjMartix);}
阅读全文
1 0
- DS-7.1实现求最小生成树的克鲁斯卡尔算法(并查集实现)
- 克鲁斯卡尔算法求最小生成树(并查集)
- hdu-1863畅通工程 最小生成树克鲁斯卡尔算法kruskal(并查集实现)&&prim普利姆算法实现
- 求最小生成树的克鲁斯卡尔(Kruskal)算法
- 最小生成树(qsort+并查集+克鲁斯卡尔(Kruskal)算法)
- 最小生成树,克鲁斯卡尔算法(Python实现)
- 克鲁斯卡算法 并查集实现最小生成树(伪代码)
- 最小生成树,普利姆算法和克鲁斯卡尔算法的C语言实现
- 最小生成树算法汇总 (普里姆 && 克鲁斯卡尔与并查集结合)
- hdu 1233(还是畅通工程)(prime算法,克鲁斯卡尔算法)(并查集,最小生成树)
- 克鲁斯卡尔(Kruskal)算法求最小生成树
- 求最小生成树_克鲁斯卡尔算法(Kruskal)
- 克鲁斯卡尔(Kruskal)算法求最小生成树
- 克鲁斯卡尔(Kruskal)算法求最小生成树
- 求最小生成树-克鲁斯卡尔算法
- 克鲁斯卡尔(Kruskal)算法求最小生成树
- 克鲁斯卡尔算法求最大/最小生成树
- java实现图的最小生成树(森林)MST克鲁斯卡尔(Kruskal)算法
- LTE
- 编辑WordPress主题的 functions.php 文件的注意事项
- 数据库
- Spring Web MVC
- jQuery怎么根据某个特定的值动态让select下的option选中
- DS-7.1实现求最小生成树的克鲁斯卡尔算法(并查集实现)
- Intellij IDEA 与 Gitlab 实现代码上传与下载
- 搜索商品点击图片切换线性布局和网格布局(代码有问题)
- 直接将普通表改为分区表
- Java解析本地文件Excel文件
- gitlab 安装报错无法重启nginx
- 获取url参数方法
- vs2013平台,C#使用mysql,安装mysql-connector-net-6.9.9-noinstall
- 邮件传输协议 SMTP 、POP3 、IMAP 和 Exchange 比较及联系?