1. 程式人生 > >hdu2066 dijkstra多源點多終點求最短路徑

hdu2066 dijkstra多源點多終點求最短路徑

dijkstra演算法的思路:

(1)找到最短距離已經確定的頂點,從它出發更新相鄰頂點的最短距離

(2)此後不再關心(1)中最短距離已經確定的頂點

最開始時只有起點的最短距離是確定的,而在未使用過的頂點中,距離d[i]最小的頂點就是最短距離已經確定的頂點,在不存在負邊的情況下d[i]不會在之後的更新中變小。  存在負邊則無法使用dijkstra

使用優先佇列實現:

#include "pch.h"
#pragma warning (disable:4996)
#include<stdio.h>
#include <iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int INF = 100000;
const int maxn = 1000 + 50;
struct edge { int to, cost; };
typedef pair<int, int> P;//first是最短距離  second是頂點編號
vector<edge>G[maxn];
int d[maxn]; int T, S, D;
int desti[maxn];
void dijkstra(int s) {
	priority_queue<P, vector<P>, greater<P> >que; //指定greater<P>引數,堆按照first從小到大的順序取出值
	fill(d, d + maxn, INF);
	d[s] = 0;
	que.push(P(0, s));
	while (!que.empty()) {
		P p = que.top();que.pop(); //取出佇列中距離最小的頂點
		int v = p.second;
		if (d[v] < p.first)continue;
		for (int i = 0;i < G[v].size();i++) {
			edge e = G[v][i];
			if (d[e.to] > d[v] + e.cost) {//如果有重邊,選擇邊權最小的
				d[e.to] = d[v] + e.cost;
				que.push(P(d[e.to], e.to));			
			}		
		}
	}
}
int main()
{
	//freopen("datain.txt","r",stdin);
	while (~scanf("%d%d%d", &T, &S, &D)) {
		int MINI = INF;
		for (int i = 0;i < maxn;i++) 
			G[i].clear();
		for (int i = 0;i < T;i++) {
			edge e, e1;	int from;
			scanf("%d%d%d", &from, &e.to, &e.cost);
			G[from].push_back(e);
			e1.to = from;e1.cost = e.cost;
			G[e.to].push_back(e1);} //無向圖正反方向都要輸入
		for (int i = 0;i < S;i++) {
			int city;
			scanf("%d", &city);
			edge e;
			e.to = city; e.cost = 0;
			G[0].push_back(e);}
		for (int i = 0;i < D;i++) 
			scanf("%d", &desti[i]);
		dijkstra(0);
		for (int i = 0;i < D;i++) {
			MINI = min(MINI, d[desti[i]]);
		}
		cout << MINI << endl;
	}
}

而圖中存在負邊的情況,則需要使用Bellman-Ford或者Floyd-Warshall演算法

Bellman-Ford:

#include "pch.h"
#pragma warning (disable:4996)
#include<stdio.h>
#include <iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#define INF 1000000
const int maxn = 1000 + 5;
using namespace std;
int d[maxn];//最短距離
int V, E;//頂點數 邊數
struct edge{
	int from, to, cost;
}edges[maxn];
void shortest_path(int s) {
	for (int i = 0;i < V;i++) d[i] = INF;
	d[s] = 0;
	while (true) {
		bool update = false;
		for (int i = 0;i < E;i++) {
			edge e = edges[i];
			if (d[e.from] != INF && d[e.to] > d[e.from] + e.cost) {
				d[e.to] = d[e.from] + e.cost;
				update = true;
			}
		}
		if (!update)break;
	}
}
bool find_negative_loop() {
	memset(d, 0, sizeof(d));
	for (int i = 0;i < V;i++) {
		for (int j = 0;j < E;j++) {
			edge e = edges[j];
			if (d[e.to] > d[e.from] + e.cost) {
				d[e.to] = d[e.from] + e.cost;
				if (i == V - 1)return true;//第V次仍然更新了
			}
		}
	}return false;
}