最小生成树(prime算法 & kruskal算法)和 最短路径算法(floyd算法 & dijkstra算法)
一、主要内容:
介绍图论中两大经典问题:最小生成树问题以及最短路径问题,以及给出解决每个问题的两种不同算法。
其中最小生成树问题可参考以下题目:
题目1012:畅通工程 http://ac.jobdu.com/problem.php?pid=1012
题目1017:还是畅通工程 http://ac.jobdu.com/problem.php?pid=1017
题目1024:畅通工程 http://ac.jobdu.com/problem.php?pid=1024
题目1028:继续畅通工程 http://ac.jobdu.com/problem.php?pid=1028
其中最短路径问题可参考一下题目:
题目1447:最短路 题目链接:http://ac.jobdu.com/problem.php?pid=1447
题目1008:最短路径问题 题目链接:http://ac.jobdu.com/problem.php?pid=1008
二、最小生成树与最短路径的定义与区别
带权图分为有向图和无向图。
无向图的最短路径又叫做最小生成树,有prime算法(普里姆算法)和kruskal算法(克鲁斯卡尔算法);
有向图的最短路径算法有floyd算法(弗洛伊德算法)和dijkstra算法(迪杰斯特拉)。
生成树的概念:连通图G的一个子图如果是一棵包含G的所有顶点的树,则该子图称为G的生成树。生成树是连通图的极小连通子图。所谓极小是指:若在树中任意增加一条边,则 将出现一个回路;若去掉一条边,将会使之变成非连通图。生成树各边的权值总和称为生成树的权。
权最小的生成树称为最小生成树,常用的算法有prime算法和kruskal算法。
最短路径问题旨在寻找图中两节点之间的最短路径,常用的算法有:floyd算法和dijkstra算法。
三、构造最小生成树的算法
构造最小生成树一般使用贪心策略,有prime算法和kruskal算法。
prime算法的基本思想:
1. 清空生成树,任取一个顶点加入生成树
2. 在那些一个端点在生成树里,另一个端点不在生成树里的边中,选取一条权最小的边,将它和另一个端点加进生成树
3. 重复步骤2,直到所有的顶点都进入了生成树为止,此时的生成树就是最小生成树.
int prime(int cur)
{
int index = cur;
int sum = ;
memset(visit, false, sizeof(visit));
visit[cur] = true;
for(int i = ; i < m; i ++){
dist[i] = graph[cur][i];
} for(int i = ; i < m; i ++){ int mincost = INF;
for(int j = ; j < m; j ++){
if(!visit[j] && dist[j] < mincost){
mincost = dist[j];
index = j;
}
} visit[index] = true;
sum += mincost; for(int j = ; j < m; j ++){
if(!visit[j] && dist[j] > graph[index][j]){
dist[j] = graph[index][j];
}
}
}
return sum;
}
Prime 算法
kruskal算法的基本思想:
1. 首先我们把所有的边按照权值先从小到大排列;
2. 接着按照顺序选取每条边,如果这条边的两个端点不属于同一集合,那么就将它们合并,直到所有的点都属于同一个集合为止。
其中用到了数据结构中的并查集。有关并查集的操作可以参考博客 http://blog.csdn.net/luomingjun12315/article/details/47373345
kruskal算法讲解推荐博客 http://www.cnblogs.com/skywang12345/p/3711500.html#anchor6
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <cmath>
#define MAX_SIZE 1010 using namespace std; int n, m;
int Tree[MAX_SIZE]; int findRoot(int x){//find the root of x
if(Tree[x]==-) return x;
else{
int tmp = findRoot(Tree[x]);//continue the find
Tree[x] = tmp;//change the root of x to tmp
return tmp;
} }
int main(){
while(scanf("%d",&n)!=EOF && n!=){//when n==0 and jump out of the loop
scanf("%d",&m);
for(int i = ; i <= n ; i++)//init
Tree[i] = -; while(m--){
int a,b;
scanf("%d%d",&a,&b);
a = findRoot(a);//find the root of a
b = findRoot(b);//find the root of b
if(a!=b) Tree[a]=b;//merge those two sets to the same aggregates
} int ans = ;
for(int i = ; i <= n ; i++){
if(Tree[i]==-) ans++;//calculate the total numbers of aggregates
}
printf("%d\n",ans-);
}
return ;
}
kruskal 算法
四、最短路径算法
最短路径问题旨在寻找图中两节点之间的最短路径,常用的算法有:floyd算法和dijkstra算法。
floyd算法是最简单的最短路径算法,可以计算图中任意两点间的最短路径;
folyd算法的时间复杂度是O(N3),如果是一个没有边权的图,把相连的两点之间的距离设为dist[i][j] = 1,不相连的两点设为无穷大,用 floyd算法可以判断i,j两点是否有路径相连。
void floyd()
{
for(int k = ; k < n; k ++){ //作为循环中间点的k必须放在最外一层循环
for(int i = ; i < n; i ++){
for(int j = ; j < n; j ++){
if(dist[i][j] > dist[i][k] + dist[k][j]){
dist[i][j] = dist[i][k] + dist[k][j]; //dist[i][j]得出的是i到j的最短路径
}
}
}
}
}
Floyd 算法
dijkstra算法用来计算从一个点到其他所有点的最短路径的算法,复杂度O(N2)。
void dijkstra(int s) //s是起点
{
memset(visit, false, sizeof(visit));
visit[s] = true;
for(int i = ; i < n; i ++){
dist[i] = graph[s][i];
} int index;
for(int i = ; i < n; i ++){
int mincost = INF;
for(int j = ; j < n; j ++){
if(!visit[j] && dist[j] < mincost){
mincost = dist[j];
index = j;
}
}
visit[index] = true;
for(int j = ; j < n; j ++){
if(!visit[j] && dist[j] > dist[index] + graph[index][j]){
dist[j] = dist[index] + graph[index][j];
}
}
}
}
dijkstra 算法
五、图论大礼包
最小生成树(prime算法 & kruskal算法)和 最短路径算法(floyd算法 & dijkstra算法)的更多相关文章
- 【啊哈!算法】算法6:只有五行的Floyd最短路算法
暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程. 上图中有 ...
- 【坐在马桶上看算法】算法6:只有五行的Floyd最短路算法
暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程. 上图中有 ...
- 最短路径 - 迪杰斯特拉(Dijkstra)算法
对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点.最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd ...
- 图论之最短路径(1)——Floyd Warshall & Dijkstra算法
开始图论学习的第二部分:最短路径. 由于知识储备还不充足,暂时不使用邻接表的方法来计算. 最短路径主要分为两部分:多源最短路径和单源最短路径问题 多源最短路径: 介绍最简单的Floyd Warshal ...
- 图的最短路径---迪杰斯特拉(Dijkstra)算法浅析
什么是最短路径 在网图和非网图中,最短路径的含义是不一样的.对于非网图没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径. 对于网图,最短路径就是指两顶点之间经过的边上权值之和最 ...
- 最短路径-迪杰斯特拉(dijkstra)算法及优化详解
简介: dijkstra算法解决图论中源点到任意一点的最短路径. 算法思想: 算法特点: dijkstra算法解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树.该算法常用于路由算 ...
- 数据结构(C#):图的最短路径问题、(Dijkstra算法)
今天曾洋老师教了有关于图的最短路径问题,现在对例子进行一个自己的理解和整理: 题目: 要求:变成计算出给出结点V1到结点V8的最短路径 答: 首先呢,我会先通过图先把从V1到V8的各种路径全部计算下来 ...
- 最短路径(floyd和Dijkstra)
最短路 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- 最短路径问题 HDU - 3790 (Dijkstra算法 + 双重权值)
参考:https://www.cnblogs.com/qiufeihai/archive/2012/03/15/2398455.html 最短路径问题 Time Limit: 2000/1000 MS ...
- Bellman-Ford & SPFA 算法——求解单源点最短路径问题
Bellman-Ford算法与另一个非常著名的Dijkstra算法一样,用于求解单源点最短路径问题.Bellman-ford算法除了可求解边权均非负的问题外,还可以解决存在负权边的问题(意义是什么,好 ...
随机推荐
- 全新升级的WiFi无线上网短信认证系统,适用于咖啡厅、足浴等公共场所,提高门门店营业收入
WiFi无线上网短信认证系统经历从1.0到1.88的升级,都是用户在使用过程中,提出宝贵的意见,一直修复至今,有着非常稳定的版本. 这个软件有什么作用?WiFi为什么要认证呢? 其实这个只是获取用户联 ...
- linux内置软件安装命令
yum -y install epel-release
- CodeFirst时使用T4模板
我们都知道T4模板用于生成相似代码. 在DBFirst和ModelFirst条件下我们很容易从.edmx下获取所有实体类和其名称,并且通过我们定义的模板和某些遍历工作为我们生成所需要的相似代码. 但是 ...
- Redis Crackit漏洞利用和防护
注意:本文只是阐述该漏洞的利用方式和如何预防.根据职业道德和<中华人民共和国计算机信息系统安全保护条例>,如果发现的别人的漏洞,千万不要轻易入侵,这个是明确的违法的哦!!! 目前Redis ...
- SPREAD for Windows Forms 下箭头追加行
''' <summary> ''' 下矢印の動作クラス ''' </summary> ''' <remarks></remarks> Public Cl ...
- 分分钟学会GCD
2014 什么是GCD Grand Central Dispatch (GCD)是异步运行任务的技术之中的一个.一般将应用程序中记述的线程管理用的代码在系统级中实现.因为线程管理是作为系统的一部分来实 ...
- Git Step by Step – (2) 本地Repo
前面一篇文章简单介绍了Git,并前在Windows平台上搭建了Git环境,现在就正式的Git使用了. Git基本概念 在开始Git的使用之前,需要先介绍一些概念,通过这些概念对Git有些基本的认识,这 ...
- Netty权威指南之Netty入门程序
package com.hjp.netty.netty; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Chan ...
- 详解 Tomcat 的连接数与线程池(转)
很不错的文章 https://juejin.im/post/5a0bf917f265da432d27a215
- IIS 7安装ModSecurity实现WAF功能
ModSecurity 是一款开源Web应用防火墙,支持Apache/Nginx/IIS,可作为服务器基础安全设施,还是不错的选择. 系统环境:window 2008 R2+IIS 7 0X01 Mo ...