题意:给出n个城市,m条无向边。每个城市中都有一定数目的救援小组,所有边的边权已知。现在给出起点和终点,求从起点到终点的最短路径条数及最短路径上的救援小组数目之和。如果有多条最短路径,则输出数目之和最大的。
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int N=505;
int n,m;//n为顶点数,m为边数
int G[N][N];//邻接矩阵
bool vis[N];//标记顶点访问与否
int d[N];//最短路径
int num[N];//最短路径条数
int weight[N];//点权
int w[N];//最大点权之和
void Dijkstra(int s){//s为起点
memset(d,INF,sizeof(d));//起点到其他点的最短路径初始化为INF
d[s]=0;//起点到起点自身的最短路径初始化为0
w[s]=weight[s];//起点到自身的最大点权之和w[s]初始化为起点的点权weight[s]
num[s]=1;//起点到自身的最短路径条数初始化为1
for(int i=0;i<n;++i){//得把整个图跑完才行吗?是的。
int u=-1,MIN=INF;
for(int j=0;j<n;++j){
if(!vis[j]&&d[j]<MIN){
u=j;
MIN=d[j];
}
}
if(u==-1) return;
vis[u]=true;
for(int v=0;v<n;++v){
if(!vis[v]&&G[u][v]!=INF){
if(d[u]+G[u][v]<d[v]){
d[v]=d[u]+G[u][v];
w[v]=w[u]+weight[v];
num[v]=num[u];
}else if(d[u]+G[u][v]==d[v]){
num[v]+=num[u];
if(w[u]+weight[v]>w[v]) w[v]=w[u]+weight[v];
}
}
}
}
}
int main(){
int c1,c2,u,v;
scanf("%d%d%d%d",&n,&m,&c1,&c2);
for(int i=0;i<n;++i)scanf("%d",&weight[i]);
memset(G,INF,sizeof(G));
for(int i=0;i<m;++i){
scanf("%d%d",&u,&v);
scanf("%d",&G[u][v]);
G[v][u]=G[u][v];
}
Dijkstra(c1);
cout<<num[c2]<<" "<<w[c2]<<endl;
return 0;
}