用HDU2544整理一下最近学的最短路算法

1.Dijkstra算法

原理:集合S表示已经找到最短路径的点,d[]表示当前各点到源点的距离

初始时,集合里面只有源点,当每个点u进入集合S时,用d[u]+w[u][v]更新距离

再重复这个步骤,选取S外所有点中d[]最小的进入集合

直到所有的点都进入S集合

局限性:图的边权必须为正

复杂度:O(V*V),堆优化((E+V)logV)

(1)用邻接矩阵实现

 #include<iostream>
#include<cstdio>
#include<cstring>
#include <cmath>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
using namespace std; typedef long long LL;
const int INF = (<<)-;
const int mod=;
const int maxn=;
int w[maxn][maxn],d[maxn],used[maxn];
int n,m; void dijkstra(int s){
memset(used,,sizeof(used));
for(int i=;i<=n;i++) d[i]=INF;
d[s]=; for(int k=;k<=n;k++){
int p,m=INF;
for(int i=;i<=n;i++) if(!used[i]&&d[i]<m) m=d[p=i];
used[p]=;
for(int i=;i<=n;i++) d[i]=min(d[i],d[p]+w[p][i]);
}
} int main(){
int a,b,c;
while(scanf("%d %d",&n,&m)!=EOF&&n&&m){
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
if(i==j) w[i][j]=;
else w[i][j]=INF;
}
} for(int i=;i<=m;i++){
scanf("%d %d %d",&a,&b,&c);
w[a][b]=w[b][a]=c;
}
dijkstra();
printf("%d\n",d[n]); }
return ;
}

(2)用邻接表实现

注意记得每次调用dijkstra()时,first[]置为-1

 #include<iostream>
#include<cstdio>
#include<cstring>
#include <cmath>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
using namespace std; typedef long long LL;
const int INF = (<<)-;
const int mod=;
const int maxn=;
int d[maxn],used[maxn],firstt[maxn],nextt[maxn];
int n,m,ecnt; struct edge{
int v,cost;
} e[maxn]; void dijkstra(int s){
memset(used,,sizeof(used));
for(int i=;i<=n;i++) d[i]=INF;
d[s]=; for(int k=;k<=n;k++){
int p,m=INF;
for(int i=;i<=n;i++) if(!used[i]&&d[i]<m) m=d[p=i];
used[p]=;
for(int i=firstt[p];i!=-;i=nextt[i]){
int v=e[i].v;
if(d[v]>d[p]+e[i].cost)
d[v]=d[p]+e[i].cost;
}
}
} void addedges(int u,int v,int w){
nextt[++ecnt]=firstt[u];
e[ecnt].v=v;
e[ecnt].cost=w;
firstt[u]=ecnt;
} int main(){
int a,b,c;
while(scanf("%d %d",&n,&m)!=EOF&&n&&m){
ecnt=;
memset(firstt,-,sizeof(firstt)); for(int i=;i<=m;i++){
scanf("%d %d %d",&a,&b,&c);
addedges(a,b,c);
addedges(b,a,c);
}
dijkstra();
printf("%d\n",d[n]);
}
return ;
}

(3)堆(优先队列)优化
参看紫书上的解释,STL中的pair是专门将两个类型捆绑起来的,

而且pair定义了它自己的排序规则,先比较第一维,相等时才比较第二维,所以需要按照(d[i],i)的顺序组合。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include <cmath>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
#define MP(a,b) make_pair(a,b)
using namespace std; typedef long long LL;
typedef pair<int,int> pii;
const int INF = (<<)-;
const int mod=;
const int maxn=;
int d[maxn],firstt[maxn],nextt[maxn];
int n,m,ecnt; struct edge{
int v,cost;
friend bool operator < (edge a,edge b){
return a.cost>b.cost;
}
}e[maxn]; void addedges(int u,int v,int c){
nextt[++ecnt]=firstt[u];
e[ecnt].v=v;
e[ecnt].cost=c;
firstt[u]=ecnt;
} void dijkstra(int s){
priority_queue<pii> pq;
for(int i=;i<=n;i++) d[i]=INF;
d[s]=;
pq.push(MP(d[s],));
while(!pq.empty()){
pii x=pq.top();pq.pop();
if(d[x.second]<x.first) continue;//当前状态没有现在dis[]数组里面的优,所以不用再继续判断下去
for(int i=firstt[x.second];i!=-;i=nextt[i]){
int v=e[i].v;
if(d[v]>d[x.second]+e[i].cost){
d[v]=d[x.second]+e[i].cost;
pq.push(MP(d[v],v));
}
}
}
} int main(){
int a,b,c;
while(scanf("%d %d",&n,&m)!=EOF&&n&&m){
memset(firstt,-,sizeof(firstt));
ecnt=;
for(int i=;i<=m;i++){
scanf("%d %d %d",&a,&b,&c);
addedges(a,b,c);
addedges(b,a,c);
}
dijkstra();
printf("%d\n",d[n]);
}
return ;
}

(4)用vector存图实现的

 #include<iostream>
#include<cstdio>
#include<cstring>
#include <cmath>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
using namespace std; typedef long long LL;
const int INF = (<<)-;
const int mod=;
const int maxn=;
int d[maxn]; typedef struct edge{
int to,distance;
edge(){}
edge(int to,int distance) :to(to),distance(distance){}
};
typedef pair<int,int> P;
vector<edge> G[maxn];
int n,m,k; void dijkstra(int s){ priority_queue<P,vector<P> ,greater<P> > q;
for(int i=;i < n;i++) d[i]=INF;
d[s]=;
q.push(P(,s)); while(!q.empty()){
P p=q.top();q.pop();
int v=p.second;
if(d[v]<p.first) continue;
for(int i=;i<G[v].size();i++){
edge e=G[v][i]; if(d[e.to] > d[v]+e.distance){ d[e.to] = d[v]+e.distance;
q.push(P(d[e.to],e.to));
}
}
}
} int main(){
while(scanf("%d %d",&n,&m)!=EOF){
if(n==&&m==) break;
for(int i=;i<n;i++) G[i].clear();
while(m--){
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
u--;v--;
G[u].push_back(edge(v,w));
G[v].push_back(edge(u,w));
}
dijkstra();
printf("%d\n",d[n-]);
} return ;
}

2.Bellman_Ford算法

原理:对于图G(V,E),Bellman_Ford是对整个图进行V-1次松弛,每次松弛检查每条边,如果d[v]>d[u]+cost,那么则更新d[v]

应用:可以用来判断负环, 如果没有负权回路的话,那么任意两点间的路径最多经过n-2个点,

即最多松弛n-1次,如果有负权回路,那么第n次松弛操作仍然会成功。

复杂度:O(VE)

 #include<iostream>
#include<cstdio>
#include<cstring>
#include <cmath>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
using namespace std; typedef long long LL;
const int INF = (<<)-;
const int mod=;
const int maxn=;
int d[maxn];
int n,m,ecnt; struct edge{
int u,v,cost;
} e[maxn]; void addedges(int u,int v,int c){
e[++ecnt].u=u;
e[ecnt].v=v;
e[ecnt].cost=c;
} void Bellman_Ford(int s){
for(int i=;i<=n;i++) d[i]=INF;
d[s]=; for(int i=;i<n;i++){
for(int j=;j<=ecnt;j++){
if(d[e[j].v]>d[e[j].u]+e[j].cost)
d[e[j].v]=d[e[j].u]+e[j].cost;
}
}
} int main(){
int a,b,c;
while(scanf("%d %d",&n,&m)!=EOF&&n&&m){
ecnt=;
for(int i=;i<=m;i++){
scanf("%d %d %d",&a,&b,&c);
addedges(a,b,c);
addedges(b,a,c);
}
Bellman_Ford();
printf("%d\n",d[n]);
}
return ;
}

Book 最短路算法的更多相关文章

  1. Dijkstra 最短路算法(只能计算出一条最短路径,所有路径用dfs)

    上周我们介绍了神奇的只有五行的 Floyd 最短路算法,它可以方便的求得任意两点的最短路径,这称为"多源最短路".本周来来介绍指定一个点(源点)到其余各个顶点的最短路径,也叫做&q ...

  2. Dijkstra最短路算法

    Dijkstra最短路算法 --转自啊哈磊[坐在马桶上看算法]算法7:Dijkstra最短路算法 上节我们介绍了神奇的只有五行的Floyd最短路算法,它可以方便的求得任意两点的最短路径,这称为“多源最 ...

  3. Floyd最短路算法

    Floyd最短路算法 ----转自啊哈磊[坐在马桶上看算法]算法6:只有五行的Floyd最短路算法 暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计 ...

  4. 近十年one-to-one最短路算法研究整理【转】

    前言:针对单源最短路算法,目前最经典的思路即标号算法,以Dijkstra算法和Bellman-Ford算法为根本演进了各种优化技术和算法.针对复杂网络,传统的优化思路是在数据结构和双向搜索上做文章,或 ...

  5. 【啊哈!算法】算法7:Dijkstra最短路算法

    上周我们介绍了神奇的只有五行的Floyd最短路算法,它可以方便的求得任意两点的最短路径,这称为“多源最短路”.本周来来介绍指定一个点(源点)到其余各个顶点的最短路径,也叫做“单源最短路径”.例如求下图 ...

  6. 【啊哈!算法】算法6:只有五行的Floyd最短路算法

            暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程.         上图中有 ...

  7. Comet OJ 热身赛(E题)(处理+最短路算法)

    dijkstra 已经提交 已经通过 42.86% Total Submission:189 Total Accepted:81 题目描述 Eagle Jump公司正在开发一款新的游戏.泷本一二三作为 ...

  8. 【最短路算法】Dijkstra+heap和SPFA的区别

    单源最短路问题(SSSP)常用的算法有Dijkstra,Bellman-Ford,这两个算法进行优化,就有了Dijkstra+heap.SPFA(Shortest Path Faster Algori ...

  9. 浅谈k短路算法

    An Old but Classic Problem 给定一个$n$个点,$m$条边的带正权有向图.给定$s$和$t$,询问$s$到$t$的所有权和为正路径中,第$k$短的长度. Notice 定义两 ...

随机推荐

  1. tar命令--解压缩

    tar命令是linux中的一个解压缩的命令.使用tar命令之前首先要搞清楚两个概念:打包和压缩.打包是指将一大堆文件或目录变成一个总的文件:压缩则是将一个大的文件通过一些压缩算法变成一个小文件. 为什 ...

  2. vi编辑器的常见使用技巧

    光标移动 在普通模式下, 1.按 h 向左移动光标 按 h + 数字n 可以向右移动 n个字符   比如 h + 5  就是向左移动5个字符 2.按j向下移动光标 3.按k向上移动光标 4.按 l 向 ...

  3. (转)Fibonacci Tilings

    Fibonacci numbers {Fn, n ≥ 0} satisfy the recurrence relation (1) Fn+2 = Fn+1 + Fn, along with the i ...

  4. POJ 3281

    Dining Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8577   Accepted: 3991 Descriptio ...

  5. cf div2 239 D

    D. Long Path time limit per test 1 second memory limit per test 256 megabytes input standard input o ...

  6. POJ 1507

    #include<iostream> #include<stdio.h> using namespace std; #include<iomanip> double ...

  7. ExtJs之Ext.core.Element

    <!DOCTYPE html> <html> <head> <title>ExtJs</title> <meta http-equiv ...

  8. 传说中的WCF(7):“单向”&“双向”

    在WCF中,服务器与客户端的通讯有单向(单工)和双向(双工)之分.要说有什么形式上的表现,那就是单向与双向生成的SOAP不同,咱们先放下代码不说.但通常情况下,我们也不太需要去研究生成的SOAP是啥样 ...

  9. 有用的一些web网站

    1.http://www.aseoe.com/api-download/download.html 爱思资源网

  10. 关于HTTP协议的学习

    HTTP(HyperTextTransferProtocol)是超文本传输协议的缩写,它用于传送WWW方式的数据,关于HTTP 协议的详细内容请参考RFC2616.HTTP协议采用了请求/响应模型.客 ...