本文是最短路径算法整理的第二篇,想阅读第一篇的朋友可以点击以下链接:
http://blog.csdn.net/hjd_love_zzt/article/details/26739593
这一篇博客继续以一些OJ上的题目为载体,整理一下最短路径算法。会陆续的更新。。。
1、HDU 2544
题目与分析:这道题抽象一下,还是:“求a到b的最短路径”。。所需要的基本条件是:点数、边数、起点、终点
以下给出floyd、dijkstra、bellmanford三种最短路径算法关于这道题的解法:
1)floyd
/* * HDU_2544.cpp * * Created on: 2014年5月31日 * Author: Administrator */ #include <iostream> #include <cstdio> using namespace std; const int maxn = 105; const int inf = 10000005; int e[maxn][maxn]; int n; void initial(){ int i; int j; for(i = 1 ; i <= n ; ++i){ for(j = 1 ; j <= n ; ++j){ if(i == j){ e[i][j] = 0; }else{ e[i][j] = inf; } } } } void floyd(){ int k; int i; int j; for(k = 1 ; k <= n ; ++k){ for(i = 1 ; i <= n ; ++i){ for(j = 1 ; j <= n ; ++j){ if(e[i][j] > e[i][k] + e[k][j]){ e[i][j] = e[i][k] + e[k][j]; } } } } } int main(){ int m; while(scanf("%d%d",&n,&m),n||m){ initial(); int i; for(i = 1 ; i <= m ; ++i){ int a,b,c; scanf("%d%d%d",&a,&b,&c); e[a][b] = e[b][a] = c; } floyd(); printf("%d\n",e[1][n]); } return 0; }
2)dijkstra
/* * HDU_2544.cpp * * Created on: 2014年5月31日 * Author: Administrator */ #include <iostream> #include <cstdio> using namespace std; const int maxn = 105; const int inf = 10000005; int n; int s[maxn]; int dis[maxn]; int map[maxn][maxn]; int target; int dijkstra(int v){ int i; for(i = 1 ; i <= n ; ++i){ s[i] = 0; dis[i] = map[v][i]; } // dis[v] = 0;//其实上面的操作已经包含这个意思了 int j; for(i = 1 ; i < n ; ++i){ int min = inf; int pos; for(j = 1 ; j <= n ; ++j){ if(!s[j] && dis[j] < min){ min = dis[j]; pos = j; } } s[pos] = 1; for(j = 1 ; j <= n ; ++j){ if(dis[j] > dis[pos] + map[pos][j]){ dis[j] = dis[pos] + map[pos][j]; } } } return dis[target]; } int main(){ int m; while(scanf("%d%d",&n,&m),n||m){ int i; int j; for(i = 1 ; i <= n ; ++i){ for(j = 1 ; j <= n ; ++j){ if(i == j){ map[i][j] = 0; }else{ map[i][j] = inf; } } } for(i = 1 ; i <= m ; ++i){ int a,b,c; scanf("%d%d%d",&a,&b,&c); map[a][b] = map[b][a] = c; } target = n; int result = dijkstra(1); printf("%d\n",result); } return 0; }
3)bellmanford
/* * HDU_2544.cpp * * Created on: 2014年5月31日 * Author: Administrator */ #include <iostream> #include <cstdio> using namespace std; struct Edge{ int u; int v; int weight; }; const int maxn = 105; const int maxm = 10005; const int inf = 1000005; Edge edge[maxm]; int dis[maxn]; int n,m; int source; bool bellmanford(){ int i; int j; for(i = 1 ; i <= n ; ++i){ dis[i] = inf; } dis[source] = 0; for(i = 1 ; i <= n ; ++i){ for(j = 1 ; j <= m ; ++j){ if(dis[edge[j].v] > dis[edge[j].u] + edge[j].weight){ dis[edge[j].v] = dis[edge[j].u] + edge[j].weight; } if(dis[edge[j].u] > dis[edge[j].v] + edge[j].weight){ dis[edge[j].u] = dis[edge[j].v] + edge[j].weight; } } } for(j = 1 ; j <= m ; ++j){ if(dis[edge[j].v] > dis[edge[j].u] + edge[j].weight){ return false; } } return true; } int main(){ while(scanf("%d%d",&n,&m),n||m){ int i; for(i = 1 ; i <= m ; ++i){ scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].weight); } source = 1; bellmanford(); printf("%d\n",dis[n]); } return 0; }
2、HDU 2066 一个人的旅行
题目分析:
这一道题还是最短路径问题。但是有以下几个不同点:
1》与平常的给出点数、边数、起点、终点不同。这道题给出了多个起点和终点、并且没有给出点数
这道题我用floyd做的时候TLE了,所以暂时只给出dijkstra解法的版本
/* * HDU_2066.cpp * * Created on: 2014年6月1日 * Author: Administrator */ #include <iostream> #include <cstdio> using namespace std; const int maxn = 1010; const int inf = 100000005; int s[1015]; int dis[1015]; int map[1015][1015]; int start, d; int from[maxn]; int want[maxn]; int dijkstra(int v) { int i; for (i = 1; i <= maxn; ++i) {//因为题目没有给出点数,所以每一次都全部扫一遍 s[i] = false; dis[i] = map[v][i]; } for (i = 1; i < maxn; ++i) { int min = inf; int pos; int j; for (j = 1; j <= maxn; ++j) { if (!s[j] && dis[j] < min) { min = dis[j]; pos = j; } } s[pos] = 1; for (j = 1; j <= maxn; ++j) { if (!s[j] && dis[j] > dis[pos] + map[pos][j]) { dis[j] = dis[pos] + map[pos][j]; } } } //到这里就已经算出以点v为起点的最短路径的情况了....这时候再遍历一下ends[],便能求出v到ends[]中哪个终点最近了 int minn = inf; for (i = 0; i < d; ++i) {//用来解决多终点的问题 int temp = dis[want[i]]; if (minn > temp) { minn = temp; } } return minn; } int main() { int t; while (scanf("%d%d%d", &t, &start, &d) != EOF) { int i; int j; for (i = 1; i <= maxn; ++i) { for (j = 1; j <= maxn; ++j) { if (i == j) { map[i][j] = map[j][i] = 0; } else { map[i][j] = map[j][i] = inf; } } } for (i = 1; i <= t; ++i) { int a, b, c; scanf("%d%d%d", &a, &b, &c); if (map[a][b] > c) { map[a][b] = map[b][a] = c; } } for (i = 0; i < start; ++i) { scanf("%d", &from[i]); } for (i = 0; i < d; ++i) { scanf("%d", &want[i]); } int result = inf; for (i = 0; i < start; ++i) {//用来解决多起点的问题 int temp = dijkstra(from[i]); if (result > temp) { result = temp; } } printf("%d\n", result); } return 0; }