模板题,学习一下最小生成树的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. String、StringBuilder

    public class testString{ public static void main(String[] args) { String a="cool"; String ...

  2. .net 类型源码下载地址

    原文:http://www.cnblogs.com/ProJKY/p/SSCLI.html 一般场景下,采用 Reflector可以反射出.NET 的部分实现出来,可以拿来参考,但和微软公开的SSCL ...

  3. HDU4010 Query on The Trees(LCT)

    人生的第一道动态树,为了弄懂它的大致原理,需要具备一些前置技能,如Splay树,树链剖分的一些概念.在这里写下一些看各种论文时候的心得,下面的代码是拷贝的CLJ的模板,别人写的模板比较可靠也方便自己学 ...

  4. POJ 2142 The Balance (解不定方程,找最小值)

    这题实际解不定方程:ax+by=c只不过题目要求我们解出的x和y 满足|x|+|y|最小,当|x|+|y|相同时,满足|ax|+|by|最小.首先用扩展欧几里德,很容易得出x和y的解.一开始不妨令a& ...

  5. mysql之select(一)

    select 初始准备工作: 1.建木瓜库并选中 create database mugua; use mugua; 2.创建商品表.栏目表.品牌表 create table goods ( good ...

  6. java for循环的几种写法

    J2SE 1.5提供了另一种形式的for循环.借助这种形式的for循环,可以用更简单地方式来遍历数组和Collection等类型的对象.本文介绍使用这种循环的具体方式,说明如何自行定义能被这样遍历的类 ...

  7. lintcode :最长公共前缀

    题目 最长公共前缀 给k个字符串,求出他们的最长公共前缀(LCP) 样例 在 "ABCD" "ABEF" 和 "ACEF" 中,  LCP ...

  8. Android SlidingMenu侧滑菜单使用

    把下载的侧滑菜单压缩包打开,会有一个library文件夹,在eclipse中import existing android code into workspace,导入library文件夹,并且选择作 ...

  9. servlet中中文乱码问题

    在web项目中经常回碰到中文乱码的问题,特此整理一下,有不足的地方,希望大家纠正. 1从前台往后台传数据,.以get方式发送请求,发送的参数不乱,但是后台接收到参数乱码 在Tomcat的server. ...

  10. 【转】SIP 中的Dialog,call,session 和 transaction

    如果你对Sip协议中Call, Dialog, Transaction和Message之间的关系感觉到迷惑,那么,那么我可以告诉你,你并不孤单,因为大多数初学者对于这些名词之间的关系都会感到疑惑.   ...