模板题,学习一下最小生成树的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的更多相关文章

  1. 最小生成树的Kruskal算法实现

    最近在复习数据结构,所以想起了之前做的一个最小生成树算法.用Kruskal算法实现的,结合堆排序可以复习回顾数据结构.现在写出来与大家分享. 最小生成树算法思想:书上说的是在一给定的无向图G = (V ...

  2. ZOJ 1203 Swordfish 旗鱼 最小生成树,Kruskal算法

    主题链接:problemId=203" target="_blank">ZOJ 1203 Swordfish 旗鱼 Swordfish Time Limit: 2 ...

  3. 经典问题----最小生成树(kruskal克鲁斯卡尔贪心算法)

    题目简述:假如有一个无向连通图,有n个顶点,有许多(带有权值即长度)边,让你用在其中选n-1条边把这n个顶点连起来,不漏掉任何一个点,然后这n-1条边的权值总和最小,就是最小生成树了,注意,不可绕成圈 ...

  4. 最小生成树 Prim Kruskal

    layout: post title: 最小生成树 Prim Kruskal date: 2017-04-29 tag: 数据结构和算法 --- 目录 TOC {:toc} 最小生成树Minimum ...

  5. 数据结构与算法--最小生成树之Kruskal算法

    数据结构与算法--最小生成树之Kruskal算法 上一节介绍了Prim算法,接着来看Kruskal算法. 我们知道Prim算法是从某个顶点开始,从现有树周围的所有邻边中选出权值最小的那条加入到MST中 ...

  6. HDU 1598 find the most comfortable road(最小生成树之Kruskal)

    题目链接: 传送门 find the most comfortable road Time Limit: 1000MS     Memory Limit: 32768 K Description XX ...

  7. 邻接矩阵c源码(构造邻接矩阵,深度优先遍历,广度优先遍历,最小生成树prim,kruskal算法)

    matrix.c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include < ...

  8. 数据结构学习笔记05图(最小生成树 Prim Kruskal)

    最小生成树Minimum Spanning Tree 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边. 树: 无回路   |V|个顶 ...

  9. HDU1875——畅通工程再续(最小生成树:Kruskal算法)

    畅通工程再续 Description相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现.现在政府决定大力发展百岛湖,发展首先要解决的问题当 ...

随机推荐

  1. 15 个最佳的 jQuery 表格插件

    现如今,网站开发设计的需求会要求自动适应所有移动设备,即响应式网站: 在开发网站时必须考虑对平板设备融合 fluid(流)和自适应性特点. 大多数网站设计要靠margins, guides, rows ...

  2. Rust: move和borrow

    感觉Rust官方的学习文档里关于ownship,borrow和lifetime介绍的太简略了,无法真正理解这些语法设计的原因以及如何使用(特别是lifetime).所以找了一些相关的blog来看,总结 ...

  3. yum install 与 yum groupinstall 的区别

    原文:http://blog.51yip.com/linux/1171.html yum 提供二种安装软件的方式 1,yum install 它安装单个软件,以及这个软件的依赖关系 2,yum gro ...

  4. HDU 4632 Palindrome subsequence(区间dp,回文串,字符处理)

    题目 参考自博客:http://blog.csdn.net/u011498819/article/details/38356675 题意:查找这样的子回文字符串(未必连续,但是有从左向右的顺序)个数. ...

  5. Gdata XML解析配置和简单使用

    导入libxml2,使用第三方AFNetworking网络请求,第三方XML解析GData GData需要的配置 Build Settings 里搜索,添加如下

  6. 思考 ”前端开发人员都在关注的 GitHub 资源“

    点这里 原文: 资源 免费的计算机编程类中文书籍 免费编程书籍 计算机科学论文 codeparkshare Python初学者书籍.视频.资料.社区推荐 Python资料汇总 app应用推荐 码农周刊 ...

  7. Apache设置禁止访问网站目录(目录列表显示文件)

    默认apache在当前目录下没有index.html入口就会显示目录.让目录暴露在外面是非常危险的事,如下操作禁止apache显示目录,希望文章对各位有帮助. 进入apache的配置文件 httpd. ...

  8. [Sharepoint]备份 迁移 还原

    在sharepoint 的备份当中,一般分为一个sharepoint 站点的备份和sharepoint 整个站点的备份.我们可以用sharepoint designer 进行备份, 也可以用 stsa ...

  9. window内存管理与内存原理

    转自: http://blog.csdn.net/iamfranter/article/details/6826270 WIndows为每个进程分配了4GB的虚拟地址空间,让每个进程都认为自己拥有4G ...

  10. (8)nehe教程2-多边形

    参考自: http://www.yakergong.net/nehe/ 你的第一个多边形: 在第一个教程的基础上,我们添加了一个三角形和一个四边形.也许你认为这很简单,但你已经迈出了一大步,要知道任何 ...