最短路的问题,先保证最短路的同时,要找权值最大的那条路,难点是还要求最短路的个数(不管权值)
用迪杰斯特拉算法,在过程中要把所有最短路的父节点记录下来,最后再处理一遍找到最短路径个数
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
const int N=500+10;
struct node
{
int p;
int d;
node(int a,int b)
{
p=a;d=b;
}
bool operator < (const node &u) const
{
return d>u.d;
}
};
vector<node> g[N];
int n,m,S,D;
int val[N],dist[N],sum[N];
int f[N],cnt[N];
bool vif[N][N];
int main()
{
memset(dist,-1,sizeof(dist));
memset(sum,0,sizeof(sum));
memset(vif,0,sizeof(vif));
scanf("%d%d%d%d",&n,&m,&S,&D);
int a,b,c;
for(int i=0;i<n;i++)
scanf("%d",&val[i]);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
g[a].push_back(node(b,c));
g[b].push_back(node(a,c));
}
//迪杰斯特拉寻找最优解+记录路径个数
priority_queue<node> q;
q.push(node(S,0));
dist[S]=0;
sum[S]=val[S];
while(!q.empty())
{
node u=q.top();
q.pop();
int pos=u.p;
int l=g[pos].size();
for(int i=0;i<l;i++)
{
int np=g[pos][i].p;
int nd=u.d+g[pos][i].d;
if(dist[np]==-1||dist[np]>=nd)
{
if(dist[np]==nd) //遇到距离相同的
{
if(!vif[np][pos]) //如果之前没有记录过,路径数+1
cnt[np]++;
vif[np][pos]=true;
if(sum[np]<sum[pos]+val[np]) //救援队更多,记录更优解
{
f[np]=pos;
sum[np]=sum[pos]+val[np];
q.push(node(np,nd));
}
}
else //距离更短,记录下来
{
cnt[np]=0;
vif[np][pos]=true;
f[np]=pos;
dist[np]=nd;
sum[np]=sum[pos]+val[np];
q.push(node(np,nd));
}
}
}
}
//BFS逆向寻找路径个数
int ans=1;
bool vis[N];
memset(vis,false,sizeof(vis));
queue<int> q0;
q0.push(D);
vis[D]=true;
while(!q0.empty())
{
int u=q0.front();
q0.pop();
ans+=cnt[u];
for(int i=0;i<=n;i++)
{
if(vif[u][i])
q0.push(i);
vis[i]=true;
}
}
//输出
stack<int> s;
int t=D;
while(t!=S)
{
t=f[t];
s.push(t);
}
printf("%d %d\n",ans,sum[D]);
while(!s.empty())
{
printf("%d ",s.top());
s.pop();
}
printf("%d\n",D);
return 0;
}