最短路径算法整理(二)

来源:互联网 发布:美工助理是做什么的 编辑:程序博客网 时间:2024/05/23 02:06

       本文是最短路径算法整理的第二篇,想阅读第一篇的朋友可以点击以下链接:

        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;}







5 0