题意:
要求你求出最短路径的数量和最多的救援队的数量,并求S到D的的路径(该路径就是路径最短且召集救援队数量最多的路径)种经过的城市?
分析:
显而易见,这题要用dijkstra算法,不会该算法的可以去学一下,这里的难点在于如何求最短路径的数量和经过的城市,我们可以用三个数组存最短路径的数量,召集救援队的数量,这个点的前驱,然后在更新其它点的时候更新这些数组吗,详情请看代码。
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <algorithm>
#include <unordered_map>
#define LL long long
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define reps(i, a, b) for(int i = a; i < b; i++)
#define pre(i, a, b) for(int i = b; i >= a; i--)
using namespace std;
const int N = 510;
int n, m, s, d;
int g[N][N];
bool st[N];
int cnt[N], number[N];
int path[N];
int dist[N], w[N];
void dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[s] = 0;
cnt[s] = w[s];
number[s] = 1;
rep(i, 1, n)
{
int t = -1;
rep(j, 0, n - 1)
if(!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
st[t] = true;
rep(j, 0, n - 1)
{
if(dist[j] > dist[t] + g[t][j])
{
dist[j] = dist[t] + g[t][j];
cnt[j] = cnt[t] + w[j];
path[j] = t;
number[j] = number[t];
}
else if(dist[j] == dist[t] + g[t][j])
{
if(cnt[j] < cnt[t] + w[j])
{
cnt[j] = cnt[t] + w[j];
path[j] = t;
}
number[j] += number[t];
}
}
}
}
int main()
{
cin >> n >> m >> s >> d;
rep(i, 0, n - 1) cin >> w[i];
rep(i, 0, n - 1) path[i] = i;
memset(g, 0x3f, sizeof g);
rep(i, 1, m)
{
int x, y, z;
cin >> x >> y >> z;
g[x][y] = z;
g[y][x] = z;
}
dijkstra();
cout << number[d] << ' ' << cnt[d] << "\n";
vector<int> ans;
int p = d;
while(1)
{
if(p == path[p])
{
ans.push_back(p);
break;
}
ans.push_back(p);
p = path[p];
}
pre(i, 0, ans.size() - 1)
{
if(i != 0) cout << ans[i] << ' ';
else cout << ans[i] << "\n";
}
return 0;
}
|