• HDU 1874 畅通工程续-- Dijkstra算法详解 单源点最短路问题


    参考

    此题Dijkstra算法,一次AC。这个算法时间复杂度O(n2)附上该算法的演示图(来自维基百科):
    附上:  迪科斯彻算法分解(优酷)
    problem link -> HDU 1874

    // HDU 1874 畅通工程续 -- 单源点最短路问题
    // 邻接矩阵 + Dijkstra
    // N 个村庄如果连通
    // 最少拥有 N-1 条道路, 最多拥有 N(N-1)/2条道路
    // 前提是任何两个村庄之间最多一条直达通道,但这个题目却有重复输入
    /* test data
    12 14
    1 3 1
    5 1 4
    5 8 3
    8 2 6
    8 4 3
    5 4 1
    3 9 5
    9 10 2
    9 7 7
    6 3 4
    6 4 4
    4 7 5
    10 7 3
    5 6 2
    1 4
    	=5
    3 3
    0 1 1
    0 2 3
    1 2 1
    0 2
    	=2
    3 1
    0 1 1
    1 2
    	=-1
    */
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int infinite = (1<<30); // 定义正无穷大(不能定义为((1<<31)-1)因为再相加会溢出) (~正无穷大 == 负无穷大)
    const int MAXV = 101; // 村庄最多的个数
    int via[MAXV][MAXV]; // 邻接矩阵
    int n_villages,n_vias;
    int d[MAXV]; // 源点S 距 点Pi的距离=d[i]
    bool flag[MAXV]; // 标记不找回头路
    
    int Dijkstra(int s,int e,int n){ // 最终结果 即最短路程 若不存在则-1
    
    	int min1 = s,min2 = 0; // via 的权值min1初始为0
    	for (int i = 0; i < MAXV ;i++)	d[i] = infinite;
    	while(min1 != e && min1 != infinite){// 找到了终点或者是找遍了整个集合 
    		flag[min1] = true;
    		int temp1=infinite,temp2=infinite;
    		for (int i = 0; i < n; i++ ){  //以 [0]-- 1 ---  [1]  为例;一开始标记了flag[0]=true so跳过
    			if (flag[i]) continue;     //     |			  |    //找到via[1][min1(此时为0)]发现比较小 数值先存起来
    											//| 3--[2] --1|    //继续找via[2][0]发现比之前的大 不存
    			if (min2 + via[i][min1]  < d[i]){        //把之前找到的那个较短值的点给min1(变成1)标记[1]为true
    				d[i] = min2 + via[i][min1];        //现在我们要做的就是该点加上之前那个最小的权看会不会比 via[i][min1]小 继续找
    			}
    			if (temp2 > d[i]){
    				temp2 = d[i];
    				temp1 = i;
    			}
    		}
    		min2 = temp2; min1 = temp1;
    	}
    	return (d[e] == infinite) ? (-1) : (d[e]);
    }
    
    void init(){
    	for (int i = 0 ; i < MAXV; i++){
    		for (int j = 0; j < MAXV ;j++)
    			via[i][j] = infinite;
    		flag[i] = false; //初始化 标记数组为 每个点都是false
    	}
    	for (int i = 0; i < n_vias; i++){
    		int a,b,d;
    		scanf("%d%d%d",&a,&b,&d);
    		if (via[a][b] > d){ // 排除输入重复的边
    			via[a][b] = d;
    			via[b][a] = d;
    		}
    	}
    }
    
    int main()
    {
    //	freopen("in.txt","r",stdin);
    	while( scanf("%d%d",&n_villages,&n_vias) != EOF ){//城镇数 和 道路数
    		init(); // 初始化 + 输入
    		int start,end;
    		scanf("%d%d",&start,&end);
    		if (start == end) {cout << "0" << endl;continue;} // 起点终点相同
    		cout << Dijkstra(start,end,n_villages) << endl;
    	}
    	return 0;
    }
    


    版权声明:本文为博主原创文章,未经博主允许不得转载。

    today lazy . tomorrow die .
  • 相关阅读:
    Codeforces Round #568 (Div. 2) D. Extra Element
    Codeforces Round #567 (Div. 2) B. Split a Number
    [dp+博弈]棋盘的必胜策略
    [暴力+前缀和]2019牛客暑期多校训练营(第六场)Upgrading Technology
    [set]Codeforces 830B-Cards Sorting
    [二分]煤气灶
    [STL] Codeforces 69E Subsegments
    剑指offer——判断B树是否是A树的子结构
    在浏览器地址栏输入URL执行后网页显示全过程
    链表反转【图解】
  • 原文地址:https://www.cnblogs.com/france/p/4808746.html
Copyright © 2020-2023  润新知