dij的简化版,比较简单。
#include<stdio.h>
using namespace std;
int n,m,s,e;
int team[502];
int mat[502][502];
int maxteam[502];
int pathcount[502];
int dist[502];
int used[502];
int INF = 1<<30;
void dij(){
dist[s] = 0;
pathcount[s] = 1;
maxteam[s] = team[s];
int i,k;
for(k=0;k<n;k++){
int p,min=INF;
for(i=0;i<n;i++) if(used[i]==0&&dist[i]<min) min = dist[p=i];//第一步先找一个最小值
if(min==INF||p==e) return;//没有找到直接返回
used[p]=1;//找到路径最小值 设该点为p 标记为已经被查找过的点
for(i=0;i<n;i++){
if(used[i]==0){//没有没有查找过
int distcost = dist[p] + mat[p][i];//从原点到i和从原点到p再到i比较谁更短
if(dist[i]>distcost){//如果更短则替换
dist[i] = distcost;
pathcount[i] = pathcount[p];//存储的是路径条数 不是之前的节点 初始值为0
maxteam[i] = maxteam[p]+team[i];//初始值为0 记录该最短路径的队伍数量
}else if(dist[i]==distcost){//两者相等的情况
pathcount[i] += pathcount[p];//增加路径数目
if(maxteam[p]+team[i]>maxteam[i])//比较两者的队伍数量 选大的
maxteam[i] = maxteam[p]+team[i];
}
}
}
}
}
int main(void){
int i,j,k;
int a,b,l;
while(scanf("%d %d %d %d",&n,&m,&s,&e)!=EOF){//输入
for(i=0;i<n;i++){
dist[i] = INF;
used[i] = 0;
maxteam[i] = 0;
pathcount[i] = 0;
for(j=0;j<n;j++)
mat[i][j]=mat[j][i] = INF;
}
for(i=0;i<n;i++){
scanf("%d",&team[i]);
}
for(i=0;i<m;i++){
scanf("%d %d %d",&a,&b,&l);
mat[a][b] = mat[b][a] = l;
}
dij();
printf("%d %d\n",pathcount[e],maxteam[e]);
}
return 0;
}