#include<bits/stdc++.h>
using namespace std;
//由于点少,直接用矩阵存边。储存图需要一个矩阵(二维数组),边数edge,点数n,
//输入前需要初始化矩阵,故要有maxv和inf。迪杰斯特拉本身带有d[]最短距离,vis[]标记数组,由于需要最短路径条数,故需要num[]记录,以及第二尺度,用weight储存信息,用w记录最大队伍数
#define MAXV 510
#define INF 10000000
int n,edge,x,y;
int d[MAXV],G[MAXV][MAXV],weight[MAXV],w[MAXV],num[MAXV];//d,num,w只在djstrea里改
bool vis[MAXV]={false};
void Djstra(int s)
{
fill(d,d+MAXV,INF);
memset(num,0,sizeof(num));
memset(w,0,sizeof(w));//d,num,w,只在djstla算法里维护,故在这里初始化
d[s]=0;
w[s]=weight[s];
num[s]=1;//这里需要注意,因为迪杰斯特拉是相当于递归算法,每次拿一个点最终算出整个图的最短路径,所以num,w,d都得有个头,即出发城市的
//但是注意不能在这里把vis[s]变成已访问,需要在下面for里找s(并且是第一个)因为
//下面维护num和w的方法跟s不一样,所以需要在这初始nums和ws
//而下面还需要把新加入点出发的路径看一遍,要么把找其路径的方法在这里再写一遍,要么就在下面再把s纳入,显然后者更合适一点
for(int i=0;i<n;i++)
{
int u=-1,MIN=INF;
for(int j=0;j<n;j++)
{
if(vis[j]==false && d[j]<MIN)
{
u=j;MIN=d[j];
}
}
if(u==-1)return;//别忘记当图不连通的时候
vis[u]=true;//vis目的就是找到每次从点集里拿到s中那个点 即u
for(int k=0;k<n;k++)//同时维护d,num,和w
{
if(vis[k]==false && G[u][k]!=INF)
{
if(d[u]+G[u][k]<d[k])
{
d[k]=d[u]+G[u][k];
num[k]=num[u];
w[k]=w[u]+weight[k];
}
else if(d[u]+G[u][k]==d[k])
{
if(w[k]<w[u]+weight[k])
{
w[k]=w[u]+weight[k];}
num[k]+=num[u];
}
}
}
}
}
int main()
{
fill(G[0],G[0]+MAXV*MAXV,INF);
scanf("%d %d %d %d",&n,&edge,&x,&y);
for(int i=0;i<n;i++)
scanf("%d",&weight[i]);
for(int i=0;i<edge;i++)
{
int temx,temy,tem;
scanf("%d %d %d",&temx,&temy,&tem);
G[temx][temy]=tem;
G[temy][temx]=tem;
}
Djstra(x);
printf("%d %d\n",num[y],w[y]);
}
裸迪杰斯特拉算最短路径是只记录最短路径多长即最短距离,不考虑第二权值,不考虑最短路径怎么走。该题要求打印出最短路径条数及第二权值最大值(不要想着不要最短距离就不维护它。
具体见代码