最小生成树之Kruskal
模板题,学习一下最小生成树的Kruskal算法
对于一个连通网(连通带权图,假定每条边上的权均为大于零的实数)来说,每棵树的权(即树中所有边的权值总和)也可能不同
具有权最小的生成树称为最小生成树
生成树:
- 无向连通图的边的集合
- 无回路
- 连接所有的点
最小:
- 所有边的权值之和最小
n个顶点的树有n-1条边
时间复杂度:O(ElogE)
对于稀疏图来说
按所给的边的权值从小到大排序,如果该边不与已经选的边形成环就选择它
这里用并查集来实现
第i条边的端点放在u、v数组中,权值保存在w中
这里用的是间接排序,也就是排的是每条边的序号,放在rank数组中
下面是两道模板题:
HDU 1863 畅通工程
//#define LOCAL
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std; const int maxn = ;
int u[maxn], v[maxn], w[maxn], parent[maxn], rank[maxn];
int m, n; bool cmp(const int i, const int j)
{
return (w[i] < w[j]);
} int GetParent(int a)
{
return parent[a] == a ? a : parent[a] = GetParent(parent[a]);
} int kruskal(void)
{
int cnt = , weight = ;
for(int i = ; i < m; ++i)
{
int edge = rank[i];
int x = GetParent(u[edge]);
int y = GetParent(v[edge]);
if(x != y)
{
weight += w[edge];
++cnt;
parent[x] = y;
}
}
if(cnt < n - ) weight = ;
return weight;
} int main(void)
{
#ifdef LOCAL
freopen("1863in.txt", "r", stdin);
#endif while(scanf("%d%d", &m, &n) == && m)
{
for(int i = ; i < m; ++i)
scanf("%d%d%d", &u[i], &v[i], &w[i]);
for(int i = ; i < n; ++i) parent[i] = i;
for(int i = ; i < m; ++i) rank[i] = i;
sort(rank, rank + m, cmp);
int ans = kruskal();
if(ans)
printf("%d\n", ans);
else
printf("?\n");
}
return ;
}
代码君一
POJ 1861 Network
感觉这道题略坑啊,它并没有说是多组输入啊,而且输出的第一个数是边里面的最大权值啊,数组开了1000多开小了啊,还有各种小错误啊。Orz
好吧,这些都是我的错误,上来就套模板,没有好好读题
//#define LOCAL
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
int v[maxn], u[maxn], r[maxn], p[maxn], w[maxn], path[maxn];
int n, m, cnt, ans; int Find(int a)
{
return p[a] == a ? a : p[a] = Find(p[a]);
} bool cmp(const int i, const int j)
{
return (w[i] < w[j]);
} void Kruskal(void)
{
cnt = , ans = -;
for(int i = ; i < m; ++i)
{
int edge = r[i];
int x = Find(u[edge]);
int y = Find(v[edge]);
if(x != y)
{
ans = max(ans, w[edge]);
p[x] = y;
path[cnt++] = i;
}
}
} void OutPut(void)
{
printf("%d\n%d\n", ans, cnt);
for(int i = ; i < cnt; ++i)
printf("%d %d\n", u[r[path[i]]], v[r[path[i]]]);
} int main(void)
{
#ifdef LOCAL
freopen("1861in.txt", "r", stdin);
#endif while(scanf("%d%d", &n, &m) == )
{
for(int i = ; i < m; ++i)
scanf("%d%d%d", &u[i], &v[i], &w[i]);
for(int i = ; i < n; ++i) p[i] = i;
for(int i = ; i < m; ++i) r[i] = i;
sort(r, r + m, cmp);
Kruskal();
OutPut();
} return ;
}
代码君二
POJ 2560 Freckles
题意:给出n个点的坐标,求最小生成树的长度。奇怪的是G++没过,C++却过了
//#define LOCAL
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std; const int maxn = + ;
struct Node
{
double x, y;
}pos[maxn]; int u[maxn], v[maxn], r[maxn], p[maxn];
double w[maxn]; bool cmp(const int i, const int j)
{
return (w[i] < w[j]);
} int Find(int a)
{
return p[a] == a ? a : p[a] = Find(p[a]);
} double Kruskal(int cnt)
{
double ans = 0.0;
for(int i = ; i < cnt; ++i)
{
int edge = r[i];
int x = Find(u[edge]);
int y = Find(v[edge]);
if(x != y)
{
ans += w[edge];
p[x] = y;
}
}
return ans;
} int main(void)
{
#ifdef LOCAL
freopen("2560in.txt", "r", stdin);
#endif int n, cnt;
while(scanf("%d", &n) == )
{
for(int i = ; i < n; ++i) p[i] = i;
for(int i = ; i < n; ++i)
scanf("%lf %lf", &pos[i].x, &pos[i].y);
cnt = ;
for(int i = ; i < n; ++i)
for(int j = ; j < i; ++j)
{
u[cnt] = i;
v[cnt] = j;
r[cnt] = cnt;
w[cnt++] = sqrt((pos[i].x-pos[j].x)*(pos[i].x-pos[j].x) + (pos[i].y-pos[j].y)*(pos[i].y-pos[j].y));
}
sort(r, r + cnt, cmp);
printf("%.2lf\n", Kruskal(cnt));
} return ;
}
代码君三
最小生成树之Kruskal的更多相关文章
- 最小生成树的Kruskal算法实现
最近在复习数据结构,所以想起了之前做的一个最小生成树算法.用Kruskal算法实现的,结合堆排序可以复习回顾数据结构.现在写出来与大家分享. 最小生成树算法思想:书上说的是在一给定的无向图G = (V ...
- ZOJ 1203 Swordfish 旗鱼 最小生成树,Kruskal算法
主题链接:problemId=203" target="_blank">ZOJ 1203 Swordfish 旗鱼 Swordfish Time Limit: 2 ...
- 经典问题----最小生成树(kruskal克鲁斯卡尔贪心算法)
题目简述:假如有一个无向连通图,有n个顶点,有许多(带有权值即长度)边,让你用在其中选n-1条边把这n个顶点连起来,不漏掉任何一个点,然后这n-1条边的权值总和最小,就是最小生成树了,注意,不可绕成圈 ...
- 最小生成树 Prim Kruskal
layout: post title: 最小生成树 Prim Kruskal date: 2017-04-29 tag: 数据结构和算法 --- 目录 TOC {:toc} 最小生成树Minimum ...
- 数据结构与算法--最小生成树之Kruskal算法
数据结构与算法--最小生成树之Kruskal算法 上一节介绍了Prim算法,接着来看Kruskal算法. 我们知道Prim算法是从某个顶点开始,从现有树周围的所有邻边中选出权值最小的那条加入到MST中 ...
- HDU 1598 find the most comfortable road(最小生成树之Kruskal)
题目链接: 传送门 find the most comfortable road Time Limit: 1000MS Memory Limit: 32768 K Description XX ...
- 邻接矩阵c源码(构造邻接矩阵,深度优先遍历,广度优先遍历,最小生成树prim,kruskal算法)
matrix.c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include < ...
- 数据结构学习笔记05图(最小生成树 Prim Kruskal)
最小生成树Minimum Spanning Tree 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边. 树: 无回路 |V|个顶 ...
- HDU1875——畅通工程再续(最小生成树:Kruskal算法)
畅通工程再续 Description相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现.现在政府决定大力发展百岛湖,发展首先要解决的问题当 ...
随机推荐
- 我收集到的最好的jQuery和CSS3导航菜单
jQuery和CSS3导航菜单在网页设计和开发的重要组成部分之一.利用jQuery+CSS3实现可以做出拥有各种动画效果的漂亮菜单.在这里,我们收集了一些最好的jQuery+CSS3实现的导航菜单. ...
- 通过HTML条件注释判断IE版本的HTML语句详解<!--[if IE]> <![endif]-->
我们常常会在网页的HTML里面看到形如[if lte IE 9]……[endif]的代码,表示的是限定某些浏览器版本才能执行的语句,那么这些判断语句的规则是什么呢?请看下文: <!--[if ! ...
- Sqli-labs less 16
Less-16 本关我们的处理方法和less15是一样的,同样的使用延时注入的方法进行解决.这里直接从源代码中看到对id进行 ("id")的处理.(请自行测试) 提交的payloa ...
- Sqli-labs less 19
Less-19 从源代码中我们可以看到我们获取到的是HTTP_REFERER 那和less18是基本一致的,我们从referer进行修改. 还是像less18一样,我们只给出一个示例 将referer ...
- 【二】php常用方法
-------------------------------数据类型------------------------------------------ 1.settype(var,type) 类 ...
- 使用git了解代码编写过程
在看教程时,有的老师会将代码放到github,如果不想跟着视频一步一步来,那就直接clone整个代码,但整个看着又有点蒙,那就使用版本切换的功能了. 首先 git clone 下载下来 git log ...
- Android 内存剖析 – 发现潜在问题
简介 移动平台上的开发和内存管理紧密相关.尽管随着科技的进步,现今移动设备上的内存大小已经达到了低端桌面设备的水平,但是现今开发的应用程序对内存的需求也在同步增长.主要问题出在设备的屏幕尺寸上-分辨率 ...
- Android activity属性
android:allowTaskReparenting 是否允许activity更换从属的任务,比如从短信息任务 切换到浏览器任务. android:alwaysRetainTaskState 是否 ...
- D&F学数据结构系列——前驱和后继
前驱和后继 本文所述为二叉排序树的前驱和后继,如果想了解二叉排序树的概念,可以参考我的博文http://www.cnblogs.com/sage-blog/p/3864640.html 给定一个二叉查 ...
- Java Applet与Java Application的特点
java application是应用程序,用于桌面开发,java applet是小应用程序,一般嵌入到网页里运行.applet一般用于B/S页面上作为插件式的开发,而application主要是桌面 ...