题目地址:
传送门
一道普通的单源最短路问题,加上最短路径条数和顶权,更新方式见代码
注意一个问题,不要加这句话。
#include <bits/stdc++.h>
using namespace std;
const int MAXVERTEX = 510;
const int INF = 0x3f3f3f;
int n, m, s, d;
int dist[MAXVERTEX];
int finish[MAXVERTEX];
//存路径
int pre[MAXVERTEX];
//存最短路径条数
int shortRoute[MAXVERTEX];
//顶权
int peopleNum[MAXVERTEX];
//存起点到各个顶点的最多救援队数量
int sumNumber[MAXVERTEX];
//边权
int G[MAXVERTEX][MAXVERTEX];
void init();
void dijstra();
void Print(int t);
stack<int> path;
int main()
{
//输入
//顶点数,边数,起点终点
cin >> n >> m >> s >> d;
//顶权
for (int i = 0; i < n; i++)
{
cin >> peopleNum[i];
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
G[i][j] = (i == j) ? 0 : INF;
}
}
while (m--)
{
int u, v, w;
cin >> u >> v >> w;
G[u][v] = G[v][u] = w;
}
dijstra();
cout << shortRoute[d] << " " << sumNumber[d] << endl;
for (int p = pre[d]; p != s; p = pre[p])
{
path.push(p);
}
cout << s << " ";
while (!path.empty())
{
cout << path.top() << " ";
path.pop();
}
cout << d;
return 0;
}
void dijstra()
{
dist[s] = 0, shortRoute[s] = 1, sumNumber[s] = peopleNum[s];
for (int i = 0; i < n; i++)
{
dist[i] = G[s][i];
}
for (int i = 0; i < n - 1; i++)
{
int min = INF, k = -1;
for (int j = 0; j < n; j++)
{
if (!finish[j] && dist[j] < min)
{
min = dist[j], k = j;
}
}
//说明这个点跟其他点不连通
if (k == -1)
break;
finish[k] = 1;
for (int j = 0; j < n; j++)
{
//能到达此节点并且没有被访问过
if (G[k][j] != INF && finish[j] == 0)
{
if (dist[k] + G[k][j] < dist[j])
{
//更新边权
dist[j] = dist[k] + G[k][j];
//更新最短路径
shortRoute[j] = shortRoute[k];
//更新顶权
sumNumber[j] = sumNumber[k] + peopleNum[j];
//存下当前节点前驱
pre[j] = k;
}
else if (dist[k] + G[k][j] == dist[j])
{
//更新最短路径条数
shortRoute[j] += shortRoute[k];
if (sumNumber[j] < sumNumber[k] + peopleNum[j])
{
//更新顶权
sumNumber[j] = sumNumber[k] + peopleNum[j];
//存下当前节点前驱
pre[j] = k;
}
}
}
}
}
}