acm算法之最短路问题
2015-08-02 11:21
405 查看
最短路问题就是求一个图中从一节点到另一节点的最短路径
(以下代码来自题目实例来自HDU1873)
算法一:Floyd五行算法 时间复杂度n^3
结果:直接求出全部两点之间最短路
适用:小数据,一次求多点之间最短路
算法二: Dijkstra 时间复杂度(m+n)log n
结果:求出一点到其他点的最短路
*进行邻接表队列优化后 时间复杂度 n log n
算法三: SPFA 时间复杂度 mn
结果:同Dijkstra
(以下代码来自题目实例来自HDU1873)
算法一:Floyd五行算法 时间复杂度n^3
结果:直接求出全部两点之间最短路
适用:小数据,一次求多点之间最短路
//Floyd n^3 原版 #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int inf = 100000000; int map[205][205]; void Floyd(int n) { int i,j,k; for(i=0;i<n;i++) for(j=0;j<n;j++) for(k=0;k<n;k++) if(map[j][i]+map[i][k]<map[j][k]) map[j][k]=map[j][i]+map[i][k]; } int main() { int n,m,i,j,x,y,z,start,end; while(~scanf("%d%d",&n,&m)) { for(i=0;i<200;i++) { for(j=0;j<200;j++) map[i][j]=inf; map[i][i]=0; } while(m--) { scanf("%d%d%d",&x,&y,&z); if(z<map[x][y]) map[x][y]=map[y][x]=z; } Floyd(n); scanf("%d%d",&start,&end); printf("%d\n",map[start][end]!=inf?map[start][end]:-1); } return 0; }
算法二: Dijkstra 时间复杂度(m+n)log n
结果:求出一点到其他点的最短路
//Dijkstra n^2 原版 #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int inf = 1<<30; int n,m; int map[300][300]; int vis[300],cast[300]; void Dijkstra(int s,int e) { int i,j,min,pos; memset(vis,0,sizeof(vis)); cast[s]=0; vis[s]=1; for(i=0;i<n;i++)cast[i]=map[s][i]; for(i=1;i<n;i++) { min=inf; for(j=0;j<n;j++) { if(cast[j]<min&&!vis[j]) { pos=j; min=cast[j]; } } vis[pos]=1; for(j=0;j<n;j++) { if(cast[pos]+map[pos][j]<cast[j]&&!vis[j]) cast[j]=cast[pos]+map[pos][j]; } } } int main() { int i,j,x,y,z,start,end; while(~scanf("%d%d",&n,&m)) { for(i = 0; i<200; i++) { for(j = 0; j<200; j++) map[i][j] = inf; map[i][i] = 0; } for(i = 0; i<m; i++) { scanf("%d%d%d",&x,&y,&z); if(z<map[x][y]) map[x][y] = map[y][x] = z; } scanf("%d%d",&start,&end); Dijkstra(start,end); printf("%d\n",cast[end]==inf?-1:cast[end]); } return 0; }
*进行邻接表队列优化后 时间复杂度 n log n
//Dijkstra nlogn 队列邻接表优化 #include <stdio.h> #include <queue> #include <string.h> #include <algorithm> using namespace std; const int inf =1<<30; const int L=1000+10; struct Edges { int x,y,w,next; }; struct node { int d; int u; node (int dd=0,int uu=0):d(dd),u(uu) {} bool operator < (const node &x) const { return u>x.u; } }; priority_queue<node> Q; Edges e[L<<2]; int head[L]; int dis[L]; int vis[L]; void AddEdge(int x,int y,int w,int k) { e[k].x = x,e[k].y = y,e[k].w = w,e[k].next = head[x],head[x] = k++; e[k].x = y,e[k].y = x,e[k].w = w,e[k].next = head[y],head[y] = k++; } void init(int n,int m) { int i; memset(e,-1,sizeof(e)); for(i = 0; i<n; i++) { dis[i] = inf; vis[i] = 0; head[i] = -1; } for(i = 0; i<2*m; i+=2) { int x,y,w; scanf("%d%d%d",&x,&y,&w); AddEdge(x,y,w,i); } } void Dijkstra(int n,int src) { node mv; int i,j,k,pre; vis[src] = 1; dis[src] = 0; Q.push(node(src,0)); for(pre = src,i = 1; i<n; i++) { for(j = head[pre]; j!=-1; j=e[j].next) { k = e[j].y; if(!vis[k] && dis[pre]+e[j].w<dis[k]) { dis[k] = dis[pre]+e[j].w; Q.push(node(e[j].y,dis[k])); } } while(!Q.empty()&&vis[Q.top().d]==1) Q.pop(); if(Q.empty()) break; mv = Q.top(); Q.pop(); vis[pre=mv.d] = 1; } } int main() { int n,m,i,j,x,y; while(~scanf("%d%d",&n,&m)) { init(n,m); scanf("%d%d",&x,&y); Dijkstra(n,x); printf("%d\n",dis[y]==inf?-1:dis[y]); } return 0; }
算法三: SPFA 时间复杂度 mn
结果:同Dijkstra
//SPFA队列优化 #include <stdio.h> #include <string.h> #include <queue> #include <algorithm> using namespace std; const int inf = 1<<30; const int L = 2000+10; struct Edges { int x,y,w,next; }e[L<<2]; int head[L]; int dis[L]; int vis[L]; int cnt[L]; int relax(int u,int v,int c)//是否进行松弛 { if(dis[v]>dis[u]+c) { dis[v]=dis[u]+c; return 1; } return 0; } void AddEdge(int x,int y,int w,int k) { e[k].x = x,e[k].y = y,e[k].w = w,e[k].next = head[x],head[x] = k++; e[k].x = y,e[k].y = x,e[k].w = w,e[k].next = head[y],head[y] = k++; } void init(int n,int m) { int i; memset(e,-1,sizeof(e)); for(i = 0; i<n; i++) { dis[i] = inf; vis[i] = 0; head[i] = -1; } for(i = 0; i<2*m; i+=2) { int x,y,w; scanf("%d%d%d",&x,&y,&w); AddEdge(x,y,w,i); } } void SPFA(int src) { int i; memset(cnt,0,sizeof(cnt)); dis[src] = 0; queue<int> Q; Q.push(src); vis[src] = 1; cnt[src]++; while(!Q.empty()) { int u,v; u = Q.front(); Q.pop(); vis[u]=0; for(i = head[u];i!=-1;i=e[i].next) { v = e[i].y; if(relax(u,v,e[i].w)==1&&!vis[v]) { Q.push(v); vis[v]=1; } } } } int main() { int n,m,i,j,x,y; while(~scanf("%d%d",&n,&m)) { init(n,m); scanf("%d%d",&x,&y); SPFA(x); printf("%d\n",dis[y]==inf?-1:dis[y]); } return 0; }
相关文章推荐
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析
- C++实现汉诺塔算法经典实例
- PHP实现克鲁斯卡尔算法实例解析
- C#获取关键字附近文字算法实例