1003. 求无向图中的最短路径,以及其中权重和最大的那条
思路:
在dj算法的基础上,还要增加两个数组:pathNum和sum。
pathNum记录从源点c1到当前点的最短路径的条数;
sum记录最短距离中权重和的最大值;
在对顶点u进行松弛的同时,更新pathNum和sum。 思路是:
- 如果松弛后的路径比之前短,则将pathNum[j]更新为pathNum[u],sum[j]更新为sum[u]+num[j];
- 如果松弛后的路径等于之前,说明产生一条新的可选路径,这时将
pathNum[j]+=pathNum[u]; sum[j]=max(sum[u]+num[j],sum[j]);
完整的代码实现为:
#include<stdlib.h>
#include<limits.h>
#include<iostream>
#include<cmath>
#include <stack>
#include<vector>
#include<string>
using namespace std;
int main(){
int n,m,c1,c2,u;
int e[500][500];
int dis[500]={0};
int book[500]={0};
int pathNum[500]={0};
int sum[500]={0};
int i=0,j=0;
int num[500]={0};
int ci=0,cj=0,length=0;
int inf=INT_MAX;
//读取顶点数n,边的条数m,源点c1,目标点c2
cin>>n>>m>>c1>>c2;
//读取每个顶点的权重num
for(i=0;i<n;i++) cin>>num[i];
//初始化邻接矩阵e
for(i=0;i<n;i++)
for(j=0;j<n;j++) {
if(i!=j) e[i][j]=inf;
else e[i][j]=0;
}
//读取每条边
for(i=0;i<m;i++) {
cin>>ci>>cj>>length;
e[cj][ci]=e[ci][cj]=length;
}
//初始化dis数组,这里是源点c1到其余各个顶点的初始路程
for(i=0;i<n;i++) dis[i]=e[c1][i];
book[c1]=1;
//初始化pathNum和sum
for(i=0;i<n;i++) {
pathNum[i] = (dis[i] == INT_MAX) ? 0 : 1;
sum[i] = (dis[i] == INT_MAX) ? INT_MIN : num[i] + num[c1];
}
sum[c1]=num[c1];
pathNum[c1]=1;
//dj算法核心部分
while(1){
int min=inf;
//找到集合Q中离源点c1最近的顶点
for(j=0;j<n;j++) {
if(book[j]==0 && dis[j]<min){
min=dis[j];
u=j;
}
}
book[u]=1;
//如果当前确定的顶点即为c2
if(u==c2){
cout<<pathNum[u]<<' '<<sum[u]<<endl;
return 0;
}
//在对顶点u进行松弛的同时,更新pathNum和sum。
for(j=0;j<n;j++) {
if(e[u][j]<inf && book[j]==0) {
if(dis[j]>(dis[u]+e[u][j])) {
dis[j]=(dis[u]+e[u][j]);
pathNum[j]=pathNum[u];
sum[j]=sum[u]+num[j];
}
else if(dis[j]==(dis[u]+e[u][j])) {
pathNum[j]+=pathNum[u];
sum[j]=max(sum[u]+num[j],sum[j]);
}
}
}
}
return 0;
}