图论算法->最短路
求最短路算法,有Floyd,dijkstra,Bellmanford,spfa等诸多高级算法。优化方法也是层出不穷。
我们不妨分析一下各算法的使用特点(可能不准确
1.Floyd算法 复杂度O(n³)可计算任意两点间最短路径 可处理负边权情况
2.Dijkstra算法 复杂度O(n²)只能计算单源最短路径 不可处理负边权情况(多源可再加一重循环)
3.Bellman-Ford算法 复杂度O(边数*点数) 计算单源最短路径 能处理负边权情况但无法处理存在负权回路情况
4.spfa算法 复杂度O(边数*玄学常数) 单源最短路径 可处理负边权情况
另外,这种算法在稀疏图上是好,而在稠密图有不乐观的一面。
另外,还有输出最短路径方案,记录前驱。参见玛丽卡一题。
我们不妨先来讨论两种图的存储方式
第一种是邻接矩阵,开了一个二维数组。如f[i][j]记录了i到j有一条边,且权值为f[i][j]
第二种是邻接表。用一个结构体+head数组记录这条边的信息
struct node{
int val,to,next;
//node存储第i条边的信息,val为第i条边的权值,to为第i条边的终
//点,next为同一起点的下一条边的第几条边数
}edge[];
int head[];//head[x]表示以x节点为起点的第一条边的边数
int tot;//tot记录已经读到第几条边
/*建边*/
void build(int x,int y,int z)
{
tot++;
edge[tot].val=z;
edge[tot].to=y;
edge[tot].next=head[x];//这里好像链表一样
head[x]=tot;
}
我们可以用这张图帮助理解。
、
长得有点像链表 是不是耶...
一、最暴力的弗洛伊德Floyd
//floyd
#include<bits/stdc++.h>
using namespace std;
const int inf=0x7f7f7f7f;
int n,m;
int w[][];
int dis[][];
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
dis[i][j]=inf;
}
for(int i=;i<=m;i++)
{
int u,v;
scanf("%d%d%d",&u,&v,&w[u][v]);
dis[u][v]=w[u][v];
}
//floyd
for(int k=;k<=n;k++)
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(dis[i][j]>dis)
dis[i][j]=dis[i][k]+dis[k][j];
//输出 dis[i][j]为i到j的最短路
return ;
}
二、Dijkstra+堆优化+邻接表
// Dijkstra
#include<bits/stdc++.h>
using namespace std;
int n,m,s;
const int inf=0x3f3f3f3f;
int tot;
bool visit[];
int head[],dis[];
struct node{
int val,to,next;
}edge[];
priority_queue< pair<int,int> > q;
//大根堆 pair第一维为dis相反数以达到小根堆效果,第二维为节点编号
void add(int x,int y,int z)
{
tot++;
edge[tot].to=y;
edge[tot].val=z;
edge[tot].next=head[x];
head[x]=tot;
}
void dijkstra()
{
for(int i=;i<=n;i++)
dis[i]=inf;
dis[s]=;//这里默认把1作为起点,求多源时可另加调整
q.push(make_pair(,s));
while(!q.empty())
{
int x=q.top().second;
q.pop();//pop会把二元组中两个元素一并弹出
if(visit[x]) continue;
visit[x]=;
for(int i=head[x];i;i=edge[i].next)
{
int y=edge[i].to;
int z=edge[i].val;
if(dis[y]>dis[x]+z&&visit[y]==)
{
dis[y]=dis[x]+z;
q.push(make_pair(-dis[y],y));
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=;i<=m;i++)
{
int x=,y=,z=;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
dijkstra();
for(int i=;i<=n;i++)
printf("%d ",dis[i]);
return ;
}
三、SPFA算法(大力拒绝bellmanford
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int inf=;
int n,m,s;
int num;
int pre[];
struct node{
int to,val,next;
}edge[];
int dis[];
bool visit[];
void add(int x,int y,int z)
{
num++;
edge[num].val=z;
edge[num].to=y;
edge[num].next=pre[x];
pre[x]=num;
}
void spfa()
{
queue<int>q;
for(int i=;i<=n;i++)
{
dis[i]=inf;
}
q.push(s);
dis[s]=;
visit[s]=;
while(!q.empty())
{
int u=q.front();
q.pop();
visit[u]=;
for(int i=pre[u];i>;i=edge[i].next)
{
int v=edge[i].to;
if(dis[v]>dis[u]+edge[i].val)
{
dis[v]=dis[u]+edge[i].val;
if(visit[v]==)
{
visit[v]=;
q.push(v);
}
} }
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=;i<=m;i++)
{
int x=,y=,z=;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
spfa();
for(int i=;i<=n;i++)
{
if(s==i) cout<<""<<" ";
else cout<<dis[i]<<" ";
} return ;
}
最后我们再来讨论一下防止溢出的问题。
建邻接表的时候,edge开到边数,无向图开二倍边;
head dis visit均存到点数即可。
图论算法->最短路的更多相关文章
- NOIp 图论算法专题总结 (1):最短路、最小生成树、最近公共祖先
系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 最短路 Floyd 基本思路:枚举所有点与点的中点,如果从中点走最短,更新两点间 ...
- 图论算法-最小费用最大流模板【EK;Dinic】
图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...
- 图论算法(一)存图与STL第六弹——vector容器
图论算法(一)存图 我发现我的博客阅读量贼低,问小伙伴们,ta们都说这些博客太长了QAQ! 今天来个短亿点的(也短不了多少……) 进入正题,图论究竟是什么? 图论就是给你一张图,让你在这张图上进行各种 ...
- 图论算法-网络最大流【EK;Dinic】
图论算法-网络最大流模板[EK;Dinic] EK模板 每次找出增广后残量网络中的最小残量增加流量 const int inf=1e9; int n,m,s,t; struct node{int v, ...
- 图论算法-Tarjan模板 【缩点;割顶;双连通分量】
图论算法-Tarjan模板 [缩点:割顶:双连通分量] 为小伙伴们总结的Tarjan三大算法 Tarjan缩点(求强连通分量) int n; int low[100010],dfn[100010]; ...
- 图论:最短路-SPFA
该算法由Bellman-Ford算法演变过来,首先介绍一下Bellman-Ford算法 最短路最多经过n-1个点,可以用n-1轮松弛操作来得到 ;i<n;i++) d[i]=INF; d[]=; ...
- 【WIP_S9】图论算法
创建: 2018/06/01 图的概念 有向边 有向图 无向边 无向图 点的次数: 点连接的边的数量 闭路: 起点和重点一样 连接图: 任意两点之间都可到达 无闭路有向图: 没有闭路的有向图 森林: ...
- tarjan图论算法
tarjan图论算法 标签: tarjan 图论 模板 洛谷P3387 [模板]缩点 算法:Tarjan有向图强连通分量+缩点+DAGdp 代码: #include <cstdio> #i ...
- [算法模版]Tarjan爷爷的几种图论算法
[算法模版]Tarjan爷爷的几种图论算法 前言 Tarjan爷爷发明了很多图论算法,这些图论算法有很多相似之处(其中一个就是我都不会).这里会对这三种算法进行简单介绍. 定义 强连通(strongl ...
随机推荐
- Springmvc 前台传递参数到后台需要数据绑定
我们知道,当提交表单时,controller会把表单元素注入到command类里,但是系统注入的只能是基本类型,如int,char,String.但当我们在command类里需要复杂类型,如Integ ...
- "格式太旧或是类型库无效。 (异常来自 HRESULT:0x80028019 (TYPE_E_UNSUPFORMAT))"
错误提示内容: “System.Runtime.InteropServices.COMException (0x80028019): 格式太旧或是类型库无效. (异常来自 HRESULT:0x8002 ...
- Centos 6.x 安装Nagios及WEB管理nagiosql实现windows及linux监控指南
一.Nagios简介 Nagios是一款开源的电脑系统和网络监视工具,能有效监控Windows.Linux和Unix的主机状态,交换机路由器等网络设置,打印机等.在系统或服务状态异常时发出邮件或短信报 ...
- Office EXCEL 如何设置最大行高
对于单个单元格行来说,行高必须在0-409之间 但是如果合并了两个单元格,则行高就扩展了一倍,不止409,而是两倍的409.
- 积跬步,聚小流------Bootstrap学习记录(3)
响应式作为Bootstrap的一大特色.栅格系统可谓是功不可没,既然如此,那我们就来看一下栅格系统是怎样帮助bootstrap实现响应式布局的呢? 1.什么是栅格系统 我们能够从Bootstrap的官 ...
- 蓝牙4.0BLE cc2540 usb-dongle的 SmartRF Packet Sniffer 抓取数据方法 【原创,多图】
蓝牙4.0BLE cc2540 usb-dongle的 SmartRF Packet Sniffer 抓取数据方法 [原创,多图] spm=a1z10.1.w4004-5319414070.11.Zd ...
- 【Java集合源代码剖析】HashMap源代码剖析
转载请注明出处:http://blog.csdn.net/ns_code/article/details/36034955 您好,我正在參加CSDN博文大赛,假设您喜欢我的文章.希望您能帮我投一票.谢 ...
- Lightoj 1012 - Guilty Prince
bfs遍历一遍就行了. /* *********************************************** Author :guanjun Created Time :2016/6/ ...
- C # 踩坑记录(20190603)
由于公司战略层需求,需要学习c#,在此仅记录相关问题,以便后期回顾. 学习路线 .NET 框架学习与C # 的关系 Visual Studio 简介及相关帮助网站(msdn) Main 方法及&quo ...
- shinx索引部分源码分析——过程:连接到CSphSource对应的sql数据源,通过fetch row取其中一行,然后解析出field,分词,获得wordhit,最后再加入到CSphSource的Hits里
CSphSource 数据源 CSphSource_XMLPipe2-XML文件获取数据 CSphSource_SQL-SQL(MySQL)获取数据 CSphIndex 索引器 派生类CSphInde ...