最短路模版整理
来源:互联网 发布:淘宝3c数码配件 编辑:程序博客网 时间:2024/05/22 12:44
接着前一篇,整理完最小生成树的模版,接下来整理一下最短路的模版。
所有题目都是根据HDU 1874 写的。
图论中求最短路的算法比较多,有Dijkstra、Bellman-ford、Floyd-Warshall、以及SPFA。主要用到的就是这么几个算法。下面一一介绍。
一、Dijkstra
这个算法的做法就是,每次找到一个距源点距离最近的点,然后扩展这个与这个点相邻的点的距离。 这个算法只能针对非负权图进行求单源最短路,算法复杂度是O(V^2)(不优化),但是可以通过堆优化(我就用优先队列写写吧。。)复杂度可以降到O(V+ElogV)
未优化模版:
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int INF = 0x3f3f3f3f;struct edge{ int u,v,next,w;}e[1005];int head[205],cnt;int d[205],vis[205];int n,m;void addedge(int u,int v,int w){ e[cnt].u = u; e[cnt].v = v; e[cnt].w = w; e[cnt].next = head[u]; head[u] = cnt++;}int Dijkstra(int s,int t){ memset(d,0x3f,sizeof(d)); memset(vis,0,sizeof(vis)); d[s] = 0; for(int i=0;i<n;i++){ int k = -1,minn = INF; for(int j=0;j<n;j++) if(!vis[j]&&d[j]<minn) minn = d[j],k = j; if(k == -1)break; vis[k] = 1; for(int j = head[k];j!=-1;j = e[j].next){ int v = e[j].v,w = e[j].w; if(!vis[v]&& d[v]>d[k]+w) d[v] = d[k]+w; } } if(d[t] == INF)return -1; return d[t];}int main(){ while(scanf("%d%d",&n,&m)==2){ int u,v,w; memset(head,-1,sizeof(head)); cnt = 0; while(m--){ scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } scanf("%d%d",&u,&v); printf("%d\n",Dijkstra(u,v)); } return 0;}
模版如下
#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;const int INF = 0x3f3f3f3f;typedef pair<int ,int > PII;struct edge{ int u,v,next,w;}e[1005];int head[205],cnt;int d[205],vis[205];int n,m;void addedge(int u,int v,int w){ e[cnt].u = u; e[cnt].v = v; e[cnt].w = w; e[cnt].next = head[u]; head[u] = cnt++;}int Dijkstra(int s,int t){ memset(d,0x3f,sizeof(d)); memset(vis,0,sizeof(vis)); d[s] = 0; priority_queue <PII,vector<PII>,greater<PII> >q; q.push(make_pair(d[s],s)); while(!q.empty()){ PII t = q.top(); q.pop(); vis[t.second] = 1; int k = t.second; for(int j = head[k];j!=-1;j = e[j].next){ int v = e[j].v,w = e[j].w; if(!vis[v]&&d[v]>d[k]+w) d[v] = d[k]+w,q.push(make_pair(d[v],v)); } } if(d[t] == INF)return -1; return d[t];}int main(){ while(scanf("%d%d",&n,&m)==2){ int u,v,w; memset(head,-1,sizeof(head)); cnt = 0; while(m--){ scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } scanf("%d%d",&u,&v); printf("%d\n",Dijkstra(u,v)); } return 0;}
二、Bellman-Ford
这个算法思想特别神奇。将起点的距离设为0,其他点设为INF,对于每一条边都做一次松弛操作。总共进行n-1次这样的操作。这样之后,dis数组里存的就是s到各点的最短距离。其实每次操作都只是更新了前一次更新的点,所以进行了很多不必要的扫描。SPFA正是把这些不必要的操作去掉得到的优化。
Bellman-Ford(普通做法 复杂度O(VE))
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int INF = 0x3f3f3f3f;struct edge{ int u,v,w;}e[1005];int n,m,cnt;int d[205];int Bellman_ford(int s){ memset(d,0x3f,sizeof(d)); d[s] = 0; for(int i=1;i<n;i++) for(int j=1;j<=cnt;j++) d[e[j].v] = min(d[e[j].v],d[e[j].u]+e[j].w); for(int i=1;i<=cnt;i++) if(d[e[i].v]>d[e[i].u]+e[i].w)return 0; return 1;}int main(){ while(scanf("%d%d",&n,&m)==2){ int u,v,w,st,ed; cnt = 0; for(int i=1;i<=m;i++){ scanf("%d%d%d",&u,&v,&w),e[++cnt].u = u,e[cnt].v = v,e[cnt].w = w; e[++cnt].u = v,e[cnt].v = u,e[cnt].w = w; } scanf("%d%d",&st,&ed); int ok = Bellman_ford(st); if(ok && d[ed]!=INF)printf("%d\n",d[ed]); else puts("-1"); } return 0;}
SPFA(好用,好写,复杂度小)
#include <iostream>#include <cstdio>#include <queue>#include <cstring>using namespace std;const int INF = 0x3f3f3f3f;struct edge{ int u,v,w,next;}e[1005];int head[205],d[205],inq[205],cnt,n,m;void addedge(int u,int v,int w){ e[cnt].u = u; e[cnt].v = v; e[cnt].w = w; e[cnt].next = head[u]; head[u] = cnt++;}int SPFA(int s){ memset(inq,0,sizeof(inq)); memset(d,0x3f,sizeof(d)); d[s] = 0; queue<int>q; q.push(s); while(!q.empty()){ int t = q.front(); q.pop(); inq[t] = 0; for(int i=head[t];i!=-1;i = e[i].next){ int v = e[i].v,w = e[i].w; if(d[v]>d[t]+w){ d[v] = d[t]+w; if(!inq[v])inq[v] = 1,q.push(v); } } } for(int i=0;i<cnt;i++) if(d[e[i].v]>d[e[i].u]+e[i].w)return 0; return 1;}int main(){ while(scanf("%d%d",&n,&m)==2){ int u,v,w,st,ed; cnt = 0; memset(head,-1,sizeof(head)); while(m--){ scanf("%d%d%d",&u,&v,&w); addedge(u,v,w),addedge(v,u,w); } scanf("%d%d",&st,&ed); int ok = SPFA(st); if(ok&&d[ed]!=INF)printf("%d\n",d[ed]); else puts("-1"); } return 0;}
三、Floyd-Warshall
这个算法非常好写,原理基于动态规划,就不细说了。。能求出任意两点间的最短路,必须使用邻接矩阵存图,复杂度是O(n^3)
模版
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int INF = 0x3f3f3f3f;int g[205][205];int n,m;int main(){ while(scanf("%d%d",&n,&m)==2){ int u,v,w; memset(g,0x3f,sizeof(g)); for(int i=1;i<=m;i++){ scanf("%d%d%d",&u,&v,&w);g[u][v] = g[v][u] = min(g[u][v],w);} int st,ed; scanf("%d%d",&st,&ed); for(int i=0;i<n;i++)g[i][i] = 0; for(int k=0;k<n;k++) for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(g[i][j]>g[i][k]+g[k][j]) g[i][j] = g[i][k]+g[k][j]; if(g[st][ed] == INF)g[st][ed] = -1; printf("%d\n",g[st][ed]); } return 0;}
算法很多,但是要把这些算法都学以致用很不容易。大概以后每道题都要想想多解,才能把这些图论算法的适用范围和自己的优势给弄清楚吧。还差了很多火候。
0 0
- 最短路模版整理
- 最短路模版
- 最短路模版
- 最短路---Dijkstra模版
- 最短路,模版
- 最短路算法模版
- HDOJ--最短路---Dijkstra模版
- 最短路模版(dijkstra)
- 最短路模版 【dijkstra】【floyd】
- POJ1511 SPFA模版 用边存的最短路
- dijkstra最短路非优化模版
- 最短路算法的整理
- 最短路最长路整理
- 模板整理: 图论---最短路
- POJ 2449 第K短路模版题 A*+最短路
- ZOJ 3166 Lazy Tourist 最短路floyd模版题
- 最短路 Dijkstra+优先队列与SPFA 模版
- 全源最短路模版
- 冒泡排序_汇编语言的子程序调用与宏定义实现
- 代码分析你的网站从SEO的角度来看
- Divide Two Integers
- Android性能优化之使用线程池
- hdu~1010(dfs)
- 最短路模版整理
- 从Ajax的Web站点中提取数据
- 丹尼尔·克雷格詹姆斯·邦德锻炼培训
- java中的堆和栈
- 个性化的价格每头服务
- VS2010 更改MFC标题栏图标和生成的执行文件图标
- 东南得克萨斯公告
- 高需求ERESOURCE ERP软件在孟买,马哈拉施特拉邦和古吉拉特邦
- 用户组删除