最短路算法
来源:互联网 发布:html嵌套php if语句 编辑:程序博客网 时间:2024/05/04 08:14
最常用的路径算法有:Bellman-Ford算法、Floyd-Warshall算法、Dijkstra算法、A*算法、Johnson算法、SPFA算法。
基本上看一遍代码就懂了
1.Bellman-Ford算法
适用于DAG图(有向无环图),及负权值中。复杂度O(VxE)
/** 单源最短路bellman_ford算法,复杂度O(VE)* 可以处理负边权图。* 可以判断是否存在负环回路。返回true,当且仅当图中不包含从源点可达的负权回路* vector<Edge>E;先E.clear()初始化,然后加入所有边* 点的编号从1开始(从0开始简单修改就可以了)*/const int INF=0x3f3f3f3f;const int MAXN=550;int dist[MAXN];struct Edge{ int u,v; int cost; Edge(int _u=0,int _v=0,int _cost=0):u(_u),v(_v),cost(_cost) {}};vector<Edge>E;bool bellman_ford(int start,int n)//点的编号从1开始{ for(int i=1; i<=n; i++)dist[i]=INF; dist[start]=0; for(int i=1; i<n; i++) //最多做n-1次 { bool flag=false; for(int j=0; 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=0; j<E.size(); j++) if(dist[E[j].v]>dist[E[j].u]+E[j].cost) return false;//有负环回路 return true;//没有负环回路}
2.Dijkstras算法
适用于权值为非负的图的单源最短路径。可用于计算正权图上的单源最短路,即从单个源点出发,到所有结点的最短路,该算法同时适用于有向图和无向图。
/** 单源最短路径,Dijkstra算法,邻接矩阵形式,复杂度为O(n^2)* 求出源beg到所有点的最短路径,传入图的顶点数,和邻接矩阵cost[][]* 返回各点的最短路径lowcost[], 路径pre[].pre[i]记录beg到i路径上的父结点,pre[beg]=-1* 可更改路径权类型,但是权值必须为非负**/const int MAXN=1010;#define typec intconst typec INF=0x3f3f3f3f;//防止后面溢出,这个不能太大bool vis[MAXN];int pre[MAXN];void Dijkstra(typec cost[][MAXN],typec lowcost[],int n,int beg){ for(int i=0; i<n; i++) { lowcost[i]=INF; vis[i]=false; pre[i]=-1; } lowcost[beg]=0; for(int j=0; j<n; j++) { int k=-1; int Min=INF; for(int i=0; i<n; i++) if(!vis[i]&&lowcost[i]<Min) { Min=lowcost[i]; k=i; } if(k==-1)break; vis[k]=true; for(int i=0; i<n; i++) if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i]) { lowcost[i]=lowcost[k]+cost[k][i]; pre[i]=k; } }}
/** Dijkstar 算法+堆优化* 使用优先队列优化Dijkstra算法* 复杂度O(ElogE)* 注意对vector<Edge>E[MAXN]进行初始化后加边*/const int INF=0x3f3f3f3f;const int MAXN=1000010;struct qnode{ int v; int c; qnode(int _v=0,int _c=0):v(_v),c(_c) {} bool operator <(const qnode &r)const { return c>r.c; }};struct Edge{ int v,cost; Edge(int _v=0,int _cost=0):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=1; i<=n; i++)dist[i]=INF; priority_queue<qnode>que; while(!que.empty())que.pop(); dist[start]=0; que.push(qnode(start,0)); qnode tmp; while(!que.empty()) { tmp=que.top(); que.pop(); int u=tmp.v; if(vis[u])continue; vis[u]=true; for(int i=0; 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));}
3.SPFA
** 单源最短路SPFA* 时间复杂度 0(kE)* 这个是队列实现,有时候改成栈实现会更加快,很容易修改* 这个复杂度是不定的*/const int MAXN=1010;const int INF=0x3f3f3f3f;struct Edge{ int v; int cost; Edge(int _v=0,int _cost=0):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=1; i<=n; i++)dist[i]=INF; vis[start]=true; dist[start]=0; queue<int>que; while(!que.empty())que.pop(); que.push(start); memset(cnt,0,sizeof(cnt)); cnt[start]=1; while(!que.empty()) { int u=que.front(); que.pop(); vis[u]=false; for(int i=0; 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;}
0 0
- JavaScript最短路算法
- 最短路算法总结
- 最短路算法总结
- 最短路 Dijkstra算法
- 最短路算法
- 最短路算法
- 最短路-Floyd算法
- 算法训练 最短路
- 最短路算法Dijkstra
- 最短路算法解析
- 最短路--SPFA算法
- 算法训练 最短路
- 最短路kruskal算法
- 最短路SPFA算法
- Dijkstra最短路算法
- 最短路算法
- 最短路算法汇总
- 最短路算法
- 备忘录模式
- Gradle 使用本地的Jar包(gradle oracle ojdbc14 )
- vmware 中dos 添加 masm
- 用Swing创建一个“注册页面”
- C中的auto、static、register和extern的区别
- 最短路算法
- 用Emacs中写LaTex以及中文配置问题
- 有关XML的知识点
- Git冲突:commit your changes or stash them before you can merge.
- 在ubuntu上安装tftp服务器与nfs服务器
- 十六进制字符串转十进制_互转
- sqlserver登陆失败
- Java中的Copy-On-Write容器
- 游戏开发中的数学和物理算法(15):矩阵的加减法