djstl做法:(相继还会跟新其它的优化做法, 现在就到这里)
#include <iostream>
#include <cstdio>
#include <cstring>
#define M 505
#define N 505
using namespace std;
const int inf = 0x3f3f3f3f;
int num[505]; // 结点权值
int map[505][505]; // 图的临近矩阵
int vis[505]; // 结点是否处理过
int ans[505]; // 最短路径结点权值和
int dis[505]; // 各点最短路径花费
int n,m,Start,End;// n结点数,m边数,Start起点,End终点
void Dij(int v){
ans[v]=num[v]; //将开始值的 分数放入 ans【v】中
memset(vis,0,sizeof(vis)); //标记数组
for(int i=0;i<n;++i){
if(map[v][i]<inf) ans[i]=ans[v]+num[i];// 开始的分数到每一个地方的分数和=当前v到i的分数和
dis[i]=map[v][i]; // 当前v到i的距离
}
dis[v]=0; //记录当前的路径长度为0
vis[v]=1; //并且当前开始走的点被访问(不在被访问)
for (int i=1;i<n;++i){ //遍历每一个值(除了第一个)
int u=0,min=inf; //u用来确定下一个最近的地点的节点
for (int j=0;j<n;++j)// min用来筛选最小的值 并确定u的值
if(!vis[j]&&dis[j]<min) min=dis[u=j];
vis[u]=1; //节点u被访问过
for(int k=0;k<n;++k) //更新两个表的值 两个表分别为最短距离表 和 权值表 是否更新-》确定该点是否被访问&&原先到k点的路径长度 比 现在该点(确定了本次的最短节点)+ 该节点到k节点的大 就进行更新
if(!vis[k]&&dis[k]>map[u][k]+dis[u]){
dis[k]=map[u][k]+dis[u];
ans[k]=ans[u]+num[k];
}
for(int k=0;k<n;++k) //如果两个路径相等 则将最大的分值加进ans【k】中
if(dis[k]==map[u][k]+dis[u])
ans[k]=max(ans[k],ans[u]+num[k]);
}
cout<<dis[End]<<" "<<ans[End]<<endl; // 输出终点最短路径花费、最短路径结点权值和
}
int main()
{
cin>>n>>m>>Start>>End;
for (int i=0;i<n;++i) cin>>num[i];
memset(vis,0,sizeof(vis));
memset(map,0x3f,sizeof(map));
for (int i=0;i<m;++i){
int x,y,z;
cin>>x>>y>>z;
if (map[x][y]>z) map[x][y]=map[y][x]=z;
}
Dij(Start);
return 0;
}