• 最短路径算法整理(二)


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

            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
    ",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
    ",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
    ",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
    ", result);
    	}
    
    	return 0;
    }
    







  • 相关阅读:
    【Todo】Java线程面试题 Top 50 (转载)
    【Todo】秒杀系统 & 乐观锁 & Nginx反向代理
    【Todo】C++和Java里面的浮点数及各种数字表示
    asp.net操作word的表格
    Android消息推送(二)--基于MQTT协议实现的推送功能
    单点更新线段树 RMQ
    英语月结
    AppWidget应用(二)---PendingIntent 之 getActivity
    2 WAN 和1 Evo/3g Routeros PCC 方法负载平衡
    Android 网络权限配置
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4297716.html
Copyright © 2020-2023  润新知