NO2——最短路径
【Dijkstra算法】
- 复杂度O(n2)
- 权值必须非负
/* 求出点beg到所有点的最短路径 */
// 邻接矩阵形式
// n:图的顶点数
// cost[][]:邻接矩阵
// pre[i]记录beg到i路径上的父结点,pre[beg]=-1
// 返回:各点的最短路径lowcost[]以及路径pre[]
const int maxn=;
const int INF=0x3f3f3f3f; //防止后面溢出,这个不能太大
bool vis[maxn];
int pre[maxn];
void Dijkstra(int cost[][maxn],int lowcost[],int n,int beg)
{
for(int i=;i<n;i++) //点的编号从0开始
{
lowcost[i]=INF;vis[i]=false;pre[i]=-;
}
lowcost[beg]=;
for(int j=;j<n;j++)
{
int k=-;
int Min=INF;
for(int i=;i<n;i++)
if(!vis[i]&&lowcost[i]<Min)
{
Min=lowcost[i];
k=i;
}
if(k==-)break;
vis[k]=true;
for(int i=;i<n;i++)
if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i])
{
lowcost[i]=lowcost[k]+cost[k][i];
pre[i]=k;
}
}
}
【Dijkstra算法+堆优化】
- 复杂度O(E*logE)
- 使用优先队列优化Dijkstra算法
//注意对vector<Edge>E[MAXN]进行初始化后加边
const int INF=0x3f3f3f3f;
const int maxn=;
struct qnode
{
int v;
int c;
qnode(int _v=,int _c=):v(_v),c(_c){}
bool operator <(const qnode &r)const
{
return c>r.c;
}
};
struct Edge
{
int v,cost;
Edge(int _v=,int _cost=):v(_v),cost(_cost){}
};
vector<Edge>E[maxn];
bool vis[maxn];
int dist[maxn];
void Dijkstra(int n,int start) //点的编号从1开始
{
memset(vis,false,sizeof(vis));
for(int i=;i<=n;i++)dist[i]=INF;
priority_queue<qnode>que;
while(!que.empty())que.pop();
dist[start]=;
que.push(qnode(start,));
qnode tmp;
while(!que.empty()){
tmp=que.top();
que.pop();
int u=tmp.v;
if(vis[u])continue;
vis[u]=true;
for(int i=;i<E[u].size();i++){
int v=E[tmp.v][i].v;
int cost=E[u][i].cost;
if(!vis[v]&&dist[v]>dist[u]+cost){
dist[v]=dist[u]+cost;
que.push(qnode(v,dist[v]));
}
}
}
}
void addedge(int u,int v,int w)
{
E[u].push_back(Edge(v,w));
}
【Bellman-ford算法】
- 复杂度O(V*E)
- 可以处理负边权图
//可以判断是否存在负环回路
//返回true,当且仅当图中不包含从源点可达的负权回路
//vector<Edge>E;
//先E.clear()初始化,然后加入所有边
const int INF=0x3f3f3f3f;
const int maxn=;
int dist[maxn];
struct Edge
{
int u,v;
int cost;
Edge(int _u=,int _v=,int _cost=):u(_u),v(_v),cost(_cost){} //构造函数
};
vector<Edge>E;
bool bellman_ford(int start,int n) //点的编号从1开始
{
for(int i=;i<=n;i++)dist[i]=INF;
dist[start]=;
for(int i=;i<n;i++) //最多做n-1次
{
bool flag=false;
for(int j=;j<E.size();j++)
{
int u=E[j].u;
int v=E[j].v;
int cost=E[j].cost;
if(dist[v]>dist[u]+cost)
{
dist[v]=dist[u]+cost;
flag=true;
}
}
if(!flag)return true; //没有负环回路
}
for(int j=;j<E.size();j++)
if(dist[E[j].v]>dist[E[j].u]+E[j].cost)
return false; //有负环回路
return true; //没有负环回路
}
【SPFA算法】
- 复杂度O(K*E)
//这个是队列实现,有时候改成栈实现会更加快,很容易修改
//这个复杂度是不定的
const int maxn=;
const int INF=0x3f3f3f3f;
struct Edge
{
int v;
int cost;
Edge(int _v=,int _cost=):v(_v),cost(_cost){}
};
vector<Edge>E[maxn];
void addedge(int u,int v,int w)
{
E[u].push_back(Edge(v,w));
}
bool vis[maxn]; //在队列标志
int cnt[maxn]; //每个点的入队列次数
int dist[maxn];
bool SPFA(int start,int n)
{
memset(vis,false,sizeof(vis));
for(int i=;i<=n;i++)dist[i]=INF;
vis[start]=true;
dist[start]=;
queue<int>que;
while(!que.empty())que.pop();
que.push(start);
memset(cnt,,sizeof(cnt));
cnt[start]=;
while(!que.empty())
{
int u=que.front();
que.pop();
vis[u]=false;
for(int i=;i<E[u].size();i++)
{
int v=E[u][i].v;
if(dist[v]>dist[u]+E[u][i].cost)
{
dist[v]=dist[u]+E[u][i].cost;
if(!vis[v])
{
vis[v]=true;
que.push(v);
if(++cnt[v]>n)return false; //cnt[i]为入队列次数,用来判定是否存在负环回路
}
}
}
}
return true;
}
【Floyd-Warshall算法】
- 复杂度O(n3)
- 边权非负
#include<cstdio>
using namespace std;
#define INF 1e9
const int maxn=+;
int n,m; //点数,边数,点从0到n-1编号
int dist[maxn][maxn]; //记录距离矩阵
int path[maxn][maxn]; //path[i][j]=x表示i到j的路径上(除i外)的第一个点是x.
void init()
{
for(int i=;i<n;i++)
for(int j=;j<n;j++)
{
dist[i][j] = i==j ? : INF; //其实这里d[i][j]应该还要通过输入读数据的
path[i][j] = j;
} //读取其他dist[i][j]的值
}
void floyd()
{
for(int k=;k<n;k++)
for(int i=;i<n;i++)
for(int j=;j<n;j++)
if(dist[i][k]<INF && dist[k][j]<INF )
{
if(dist[i][j]>dist[i][k]+dist[k][j])
{
dist[i][j] = dist[i][k]+dist[k][j];
path[i][j] = path[i][k];
}
else if(dist[i][j] == dist[i][k]+dist[k][j] &&path[i][j]>path[i][k])
{
path[i][j] = path[i][k]; //最终path中存的是字典序最小的路径
}
}
} int main()
{
//读n和m
init();
//读m条边
floyd();
//输出所求最短路径距离
return ;
}
NO2——最短路径的更多相关文章
- Johnson 全源最短路径算法
解决单源最短路径问题(Single Source Shortest Paths Problem)的算法包括: Dijkstra 单源最短路径算法:时间复杂度为 O(E + VlogV),要求权值非负: ...
- Floyd-Warshall 全源最短路径算法
Floyd-Warshall 算法采用动态规划方案来解决在一个有向图 G = (V, E) 上每对顶点间的最短路径问题,即全源最短路径问题(All-Pairs Shortest Paths Probl ...
- Dijkstra 单源最短路径算法
Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...
- Bellman-Ford 单源最短路径算法
Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Leste ...
- 最短路径算法-Dijkstra
Dijkstra是解决单源最短路径的一般方法,属于一种贪婪算法. 所谓单源最短路径是指在一个赋权有向图中,从某一点出发,到另一点的最短路径. 以python代码为例,实现Dijkstra算法 1.数据 ...
- bzoj 4016: [FJOI2014]最短路径树问题
bzoj4016 最短路路径问题 Time Limit: 5 Sec Memory Limit: 512 MB Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点 ...
- 51nod 1459 迷宫游戏 (最短路径—Dijkstra算法)
题目链接 中文题,迪杰斯特拉最短路径算法模板题. #include<stdio.h> #include<string.h> #define INF 0x3f3f3f3f ],v ...
- C++迪杰斯特拉算法求最短路径
一:算法历史 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以 ...
- 求两点之间最短路径-Dijkstra算法
Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.D ...
随机推荐
- (Linux 日常命令)[20171225]
目的:记录Linux日常所用命令 [20171222]Linux环境下查看硬件组件型号 cat /proc/cpuinfo及lspci 查看CPU [root@t-redhat- ~]# cat /p ...
- sqlite内存数据库和文件数据库的同步[转]
由于sqlite对多进程操作支持效果不太理想,在项目中,为了避免频繁读写 文件数据库带来的性能损耗,我们可以采用操作sqlite内存数据库,并将内存数据库定时同步到文件数据库中的方法. 实现思路如下: ...
- GUI小程序---理解GUI
package com.gui; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent ...
- 洛谷 P3952
题目描述 小明正在学习一种新的编程语言 A++,刚学会循环语句的他激动地写了好多程序并 给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序, 于是你的机会来啦!下面请你编写程序 ...
- 我是一个MySQL小白
我是一个MySQL小白 第一回早起装扮 “mysql,Oracle,SQL-SERVER你们三个 起床没?”,清晨七点多师父喊道. “师父,我(mysql)哪敢睡觉呀,我还在查询表呢,有客户的密码忘记 ...
- python基础,导入模块,if语句,while语句
python基础 python代码 变为字节码 变为机器码 最后执行执行‘文件名.py’文件时出现的‘文件名.pyc’文件为字节码 缓存机制 使用pycharm的时候在文件最开始添加下面这两行代码,中 ...
- ruby $LOAD_PATH及类加载
$LOAD_PATH $LOAD_PATH 指的是Ruby读取外部文件的一个环境变量,其实和windows的环境变量是一个概念.Ruby会在这个环境变量的路径中读取需要require的文件,如果在环境 ...
- 勾股数--Python
勾股数:勾股数又名毕氏三元数 .勾股数就是可以构成一个直角三角形三边的一组正整数.勾股定理:直角三角形两条直角边a.b的平方和等于斜边c的平方(a²+b²=c²) 要求:输出1000以内的勾股数 fr ...
- linux网络服务实验
1.设置window IP地址为192.168.3.XX,掩码24位. 2.设置Linux IP地址为192.168.3.YY,掩码24位.window与Linux互相ping通. 3.在linux中 ...
- ffplay使用笔记
ffplay播放yuv文件命令: ffplay -f rawvideo -video_size 1920x1080 a.yuv ffplay播放mp4.h.264.hevc文件命令: ffplay ...