最短路 DijkstraFloyd SPFA三种算法

    xiaoxiao2021-03-25  78

    三种算法  都是最短路  经典的算法,  三者的复杂度依次为 O(n)^2  O (n)^3  O(n)^2

    可以看到,Floyd  复杂度最大 一般处理100 以内的数据左右

     

    三种算法的适用范围:

    Dijkstra:适用于权值为非负的图的单源最短路径,用斐波那契堆的复杂度O(E+VlgV)

    SPFA:适用于权值有负值,且没有负圈的图的单源最短路径,论文中的复杂度O(kE),k为每个节点进入Queue的次数,且k一般<=2,但此处的复杂度证明是有问题的,其实SPFA的最坏情况应该是O(VE). Floyd:每对节点之间的最短路径。 (1)当权值为非负时,用Dijkstra。 (2)当权值有负值,且没有负圈,则用SPFA,SPFA能检测负圈,但是不能输出负圈。 (3)SPFA检测负环:当存在一个点入队大于等于V次,则有负环, 先给出三种算法的 模板  我们要注意 在  数组 (邻接矩阵))初始化 以及在输入数据时 :

    如果是 无向图 则 应该是 map[x][y]=map[y][x]=s;

    如果是 有向图 则 应该是 map[x][y]=s;

    以及在初始化时  if(i==j) map[i][j]=0  或 map[i][j]=1(如果下面用到的是 乘积);

    Dijstra /* Dijkstra 算法 模板 */ const int MAX=1<<29; const int N= 1000; int map[N][N];//邻接矩阵 int dist[N];//更新点 bool vis[N];//设置已访问 int n,m; void Dijkstra(int x)//x 为 起始点 { int i,j,mid,u; for(i=0;i<n;i++) { dist[i]=map[x][i]; vis[i]=false; } vis[x]=true;//起点已访问 dist[x]=0; for(j=2;j<=n;j++) { mid=MAX; u=0; for(i=0;i<=n;i++) { if(!vis[i]&&dist[i]<mid) { mid=dist[i]; u=i; } } vis[u]=true; for(i=0;i<=n;i++) { if(!vis[i]&&dist[u]+ma[u][i]<dist[i]) dist[i]=dist[u]+ma[u][i];//更新 } } } int main() { for(i=0;i<=n;i++) for(j=0;j<=n;j++) { if(i==j) map[i][j]=0;// 自己到自己 距离为0; else map[i][j]=MAX; //初始化最大 } /* 输入数据时 如果是 无向图 邻接矩阵应该是 map[x][y]=map[y][x]=z; 如果是有向图 则应该是map[x][y]=z; */ } Floyd 模板 /* Floyd 算法模板 */ for(k=0;k<n;k++) { for(i=0;i<n;i++) { for(j=0;j<n;j++) if(map[i][j]>(map[i][k]+map[k][j])) { map[i][j]=map[i][k]+A[k][j]; } // if(判断) } } SPFA 算法  用到的是 queue 队列  // SPFA 算法模板 queue #include<stdio.h> #include<queue> bool vis[N]; void SPFA(int s) { queue<int>Q; for(int i=0; i<=n; i++) dis[i]=MAX; //初始化每点i到s的距离 dis[s]=0; vis[s]=1; //设置访问 Q.push(s); //队列初始化,s为起点 压入队列 int i, v; while (!Q.empty()) { //队列非空 v=Q.front();//取队 头 Q.pop(); // 释放队首结点,因为这节点可能下次用来松弛其它节点,重新入队 for(i=0; i<=n; i++) //对所有顶点 if (dis[i]>dis[v]+map[v][i]) { dis[i] = dis[v]+map[v][i]; //修改最短路 if (!vis[i]) { //如果扩展结点i不在队列中,入队 vis[i]=true;//设置访问 Q.push(i); } } } } 三种算法的具体 理解思路 可以看下下面 的博客 Dijstra and Floyd :   http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html  SPFA :    http://blog.csdn.net/muxidreamtohit/article/details/7894298 下面是 poj的 一些 最短路 题目

    POJ 2387 1797 3268  Dijstra

    POJ 3259 2240 Floyd  3660 1511 2502

    poj 2387 :  http://poj.org/problem?id=2387   经典 Dijstra  直接套模板

    poj 1797 :  http://poj.org/problem?id=1797   Dijstra  变形, 修改判断条件  找最小里面的最大 max(min(a,b),c);

    poj 3268 : http://poj.org/problem?id=3268   也是Dijstra  调用两次Dijstra  一个来一个去 或 矩阵置换;

    poj  3259: http://poj.org/problem?id=3259   虫洞问题, 可以用Floyd  用到负权值, 需要负 ;

    poj  2240: http://poj.org/problem?id=2240   美元兑换问题 可以用spfa 或者floyd;  只要 最后兑换到自己 大于1.0  则yes  否则no ;

     

    传送门:

    poj 2387 : http://blog.csdn.net/pingjijnming/article/details/60574074

    poj 1797 : http://blog.csdn.net/pingjijnming/article/details/60777478 poj 3268 : http://blog.csdn.net/sizaif/article/details/60964043 poj  3259: http://blog.csdn.net/sizaif/article/details/60964517 poj  2240: http://blog.csdn.net/sizaif/article/details/60963759

    转载请注明原文地址: https://ju.6miu.com/read-13851.html

    最新回复(0)