最短路径算法整理(二)

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

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







郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。