佛山网站建设设计公司关键词如何确定
这个题目整合了我们最短路用到的很多技能
如何统计最短路径的方案数呢,这就需要我们另外开一个全局数组
如何打印路径呢,还是开一个全局的数组,记录前一个是啥就行
简单的来说,要增加啥新的功能,直接多开全局变量就行,没必要写在优先队列里面,不好转换
题目地址
#include<bits/stdc++.h>
using namespace std;const int N = (int)505;
int n,m,s,d;
int num[N];
// 没有说明有多少条边
struct node{int v,w;
};vector<node> ed[N];
vector<int> path(N,-1);vector<int> cnt(N,0);
vector<int> shu(N,0);void fun(){vector<int> dis(n,0x3f3f3f3f);vector<int> vis(n,0);priority_queue<pair<int,int>,vector<pair<int,int>>,greater<>> q;q.push({0,s});cnt[s] = 1;shu[s] = num[s];dis[s] = 0;while(q.size()){auto now = q.top();q.pop();int d = now.first, u = now.second;if(vis[u]) continue;vis[u] = 1;for(int i=0;i<ed[u].size();i++){int v = ed[u][i].v, w = ed[u][i].w;if(d+w<dis[v]){ // 这里还是很正常的最短路dis[v] = d + w;cnt[v] = cnt[u];shu[v] = shu[u] + num[v];path[v] = u;q.push({dis[v],v});}else if(d+w==dis[v]){ // 如果距离相等就需要加上这条路径上的方案数cnt[v] += cnt[u];if(shu[v]<shu[u]+num[v]){ // 相同距离下,如果救援队的数量更多,就采取这条新的路径path[v] = u;shu[v] = shu[u] + num[v];}}}}}int main(){cin >> n >> m >> s >> d;for(int i=0;i<n;i++){cin >> num[i];}int u,v,w;for(int i=1;i<=m;i++){cin>>u>>v>>w;ed[u].push_back({v,w});ed[v].push_back({u,w});}fun();cout << cnt[d] << " " << shu[d] << endl;vector<int> ans;int now = d;while(path[now]!=-1){ans.push_back(path[now]);now = path[now];}for(int i=ans.size()-1;i>=0;i--){cout << ans[i] << " ";}cout << d;return 0;
}
要弄清楚的就是距离相同的时候,如何进行转换,距离相同的时候,救援队的数量就是我们需要考虑的因素,我们直接采取新的路径就行
可能有的疑惑是为什么路径相等的时候不再次将这个节点push到堆中,这是因为我们的堆中肯定存在这个节点了,且一定没有遍历到,这是因为我们的当前的距离是d , 而v节点的距离dis[v] == d + w,这么说dis[v]大于d,那么v节点一定存在于堆中,我们就没必要重复push进去了