一、題目
二、思路
在Dijkstra算法的基礎上,統計最短路徑條數和最大頂點權值(消防隊數目)。需判斷什麼時候出現相同最短路徑(D[j] == D[k] + dist[k][j]
),出現後,tot數組該如何變化(tot[j]+=tot[k];
)。最大消防隊比較容易。
三、代碼
int N,D[500],s[500],tot[500],team[500],num[500];
//N-城市數,D最短路徑數組,s標記數組,tot相同最短路徑數目,team每個城市擁有的消防隊數目,num召集的消防隊數目
void Dijkstra(int v,int dist[][500]) {
int i, j, k, v1, min, max = 10000;
v1 = v;
for (i = 0; i < N; i++) {//初始化D、s、tot、num
D[i] = dist[v1][i];
s[i] = 0;
if (D[i] == max) {//表明c1到該點沒有邊
tot[i] = 0;
num[i] = 0;
}
else {
tot[i] = 1;
num[i] = team[v1]+team[i];
}
}
s[v1] = 1; num[v1] = team[v1];//對c1的單獨初始化
for (i = 0; i < N - 1; i++) {
min = max + 1;//保證所有頂點都能被訪問
//尋找最短路徑
for (j = 0; j < N; j++) {
if ((s[j] == 0) && (D[j] < min)) {
min = D[j]; k = j;
}
}
s[k] = 1;
//修改部分
for (j = 0; j < N; j++) {
if ((s[j] == 0) && (D[j] > D[k] + dist[k][j])) {
D[j] = D[k] + dist[k][j];
tot[j] = tot[k];
num[j] = num[k] + team[j];//由於路徑改了,經過的頂點也就變了,這裏必須變
}
else if ((s[j] == 0) && (D[j] == D[k] + dist[k][j])) {//出現相同最短路徑
tot[j]+=tot[k];
if (num[j] < num[k] + team[j])//需要判斷下哪個引起的消防隊更多
num[j] = num[k] + team[j];
}
}
}
return;
}
int main() {
int M, c1, c2, i, j, dist[500][500] = { 0 }, ct1, ct2;//dist鄰接矩陣
scanf("%d %d %d %d", &N, &M, &c1, &c2);
for (i = 0; i < N; i++)
scanf("%d", &team[i]);
for (i = 0; i < M; i++) {
scanf("%d %d", &ct1, &ct2);
scanf("%d", &dist[ct1][ct2]);
dist[ct2][ct1] = dist[ct1][ct2];
}
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
if ((i != j) && (dist[i][j] == 0))
dist[i][j] = 10000;
Dijkstra(c1, dist);
printf("%d %d", tot[c2], num[c2]);
return 0;
}