题解:洛谷 P1608 路径统计
题目https://www.luogu.com.cn/problem/P1608本题除了求出最短路,还需要求出最短路径的条数。
最短路的部分我就不说多了(跑一遍 Dijkstra 解决),主要是统计出最短路径的条数。
如果 ,即原来的最短路被替换掉了,那么我们用现在的最短路径条数替换掉原来的(即 )。
如果最短路径长度相同,那么更新最短路径条数()。
实现
#include<bits/stdc++.h>
using namespace std;
#define int long long
int dp[2005],n,m,dis[2005],G[2005][2005];
vector<pair<int,int>>v[2005];
bool vis[2005];
void Dijkstra(int Begin){
fill(vis,vis+n+1,false);
fill(dis,dis+n+1,1e18);
priority_queue<pair<int,int>>q;
dp[Begin]=1,dis[Begin]=0;
q.push({dis[Begin],Begin});
while(q.size()){
auto p=q.top();
q.pop();
if(!vis[p.second]){
vis[p.second]=true;
for(auto z:v[p.second]){
if(!vis[z.first]){
if(dis[z.first]>dis[p.second]+z.second){
dp[z.first]=dp[p.second];
dis[z.first]=dis[p.second]+z.second;
q.push({-dis[z.first],z.first});
}else if(dis[z.first]==dis[p.second]+z.second){
dp[z.first]+=dp[p.second];
}
}
}
}
}
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m;
fill(G[0],G[n+1],1e18);
for(int i=1,x,y,z;i<=m;i++){
cin>>x>>y>>z;
G[x][y]=min(G[x][y],z);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(G[i][j]!=1e18){
v[i].push_back({j,G[i][j]});
}
}
}
Dijkstra(1);
cout<<(dis[n]==1e18?"No answer":to_string(dis[n])+" "+to_string(dp[n]));
return 0;
}