1. 程式人生 > >PTAL2-001 緊急救援解題報告---Dijkstra拓展(最短路條數 & 前驅結點記錄 & 結點值最大和)

PTAL2-001 緊急救援解題報告---Dijkstra拓展(最短路條數 & 前驅結點記錄 & 結點值最大和)

                                     L2-001 緊急救援 (25 分)

作為一個城市的應急救援隊伍的負責人,你有一張特殊的全國地圖。在地圖上顯示有多個分散的城市和一些連線城市的快速道路。每個城市的救援隊數量和每一條連線兩個城市的快速道路長度都標在地圖上。當其他城市有緊急求助電話給你的時候,你的任務是帶領你的救援隊儘快趕往事發地,同時,一路上召集儘可能多的救援隊。

輸入格式:

輸入第一行給出4個正整數N、M、S、D,其中N(2≤N≤500)是城市的個數,順便假設城市的編號為0 ~ (N−1);M是快速道路的條數;S是出發地的城市編號;D是目的地的城市編號。

第二行給出N個正整數,其中第i個數是第i個城市的救援隊的數目,數字間以空格分隔。隨後的M行中,每行給出一條快速道路的資訊,分別是:城市1、城市2、快速道路的長度,中間用空格分開,數字均為整數且不超過500。輸入保證救援可行且最優解唯一。

輸出格式:

第一行輸出最短路徑的條數和能夠召集的最多的救援隊數量。第二行輸出從S到D的路徑中經過的城市編號。數字間以空格分隔,輸出結尾不能有多餘空格。

輸入樣例:

4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2

輸出樣例:

2 60
0 1 3

Dijkstra的變形強化 

AC Code: 

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#include<cctype>
#include<map>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#define INF 0x3f3f3f3f
using namespace std;
static const int MAX_N = 1e5 + 5;
typedef long long ll;
int path[505][505], vv[505], dis[505];	//兩點距離,結點權值,s到任意點最短距離
bool vis[505];		//標記
int maxval[505], pathcount[505], pre[505];	//最大結點和,最短路徑數,前驅結點記錄
int s, d, n;

void preprint(int e) {	//最前結點開始遍歷
	if (pre[e] != -1) {
		preprint(pre[e]);
		printf("%d ", pre[e]);
	}
}
void Dijkstra() {
	for (int i = 0; i < n; i++) {
		dis[i] = path[s][i];
	}
	//vis[s] = true;
	maxval[s] = vv[s];
	pathcount[s] = 1;
	for (int i = 0; i < n; i++) {
		int mins = INF, pres = s;
		for (int j = 0; j < n; j++) {
			if (!vis[j] && mins > dis[j]) {
				mins = dis[j];
				pres = j;
			}
		}
		if (mins == INF) break;
		vis[pres] = true;
		for (int j = 0; j < n; j++) {
			if (!vis[j]) {
				if(dis[j] > dis[pres] + path[pres][j]){	//存在更短路
					dis[j] = dis[pres] + path[pres][j];
					maxval[j] = maxval[pres] + vv[j];
					pathcount[j] = pathcount[pres];
					pre[j] = pres;
				}
				else if (dis[j] == dis[pres] + path[pres][j]) {	//最短路條數增加
					pathcount[j] += pathcount[pres];
					if (maxval[j] < maxval[pres] + vv[j]) {	//存在更大權值
						maxval[j] = maxval[pres] + vv[j];
						pre[j] = pres;
					}
				}
			}
		}
	}
}
int main(){
	int m;
	for (int i = 0; i < 505; i++) {
		vis[i] = false;
		maxval[i] = 0;
		pathcount[i] = 0;
		pre[i] = -1;
		for (int j = 0; j < 505; j++) {
			i == j ? path[i][j] = 0 : path[i][j] = path[j][i] = INF;
		}
	}
	scanf("%d%d%d%d", &n, &m, &s, &d);
	for (int i = 0; i < n; i++) scanf("%d", &vv[i]);
	for (int i = 0; i < m; i++) {
		int u, v, t;
		scanf("%d%d%d", &u, &v, &t);
		if (path[u][v] > t) {
			path[u][v] = path[v][u] = t;
		}
	}
	Dijkstra();
	printf("%d %d\n", pathcount[d], maxval[d]);	//最短路數與最大權值和
	preprint(d);	//列印路徑
	printf("%d\n", d);	
	return 0;
}