更新内容:
源程序的算法理解之后,用例只对了一个,经过排查发现是fill()和memset()的用法不清造成的。
//fill()按照单元赋值,将一个区间内的元素都赋同一个值,使用的话需要algorithm头文件
//memset()是按照字节填充内容,在头文件cstring中
//因此memset一般都是用来填充char型数组的,对于int类型数组只能填充0或者-1
//而fill对于int型数组则更加方便一些
//例如:
int num[maxn];
fill(num, num+maxn, 100);
//则将num数组的每个元素都填充为100
vector<int> vec;
fill(vec.begin(), vec.end(), 1000);
//对于memset,下面的方法也是可以的
int num[maxn];
memset(num, 0, sizeof(num));
源程序如下:
//该题是经典模板题,终于将dijkstra理清了
//题目给出的输入数据是顶点数n,边数m,起始顶点和目标顶点st\ed
//给出每条路的端点和路径长度,为int类型
//以及一组顶点权重,最后求st到ed的最短路径条数和所得到顶点权值和的最大值
//核心就是dijstra算法
//尝试一下
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int maxv = 550;
const int INF = 1000000000;
int d[maxv];
int num[maxv];
int w[maxv];
int n, m, st, ed;
int weight[maxv];
bool vis[maxv] = {false};
int G[maxv][maxv];
void Dijkstra(int st){
//Initialization
//memset(d, INF, sizeof(d));
fill(d, d+maxv, INF);
memset(num, 0, sizeof(num));
memset(w, 0, sizeof(w));
//错误主要处在fill 和memset上
d[st] = 0;
num[st] = 1;
w[st] = weight[st];
for(int i=0;i<n;i++){
int u = -1, min_dis = INF;
for(int j=0;j<n;j++){
if(vis[j]==false && d[j]<min_dis){
u = j;
min_dis = d[j];
}
}
if(u==-1) return;
vis[u] = true;
//这句千万不要忘记,将当前轮得到的最短路径真值所对应的点加入到完成点集中
for(int v=0;v<n;v++){
if(vis[v]==false && 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]){
if(w[u]+weight[v]>w[v]){
w[v] = w[u] + weight[v];
}
num[v] += num[u];
}
}
}
}
}
int main(){
fill(G[0], G[0] + maxv*maxv, INF);
scanf("%d%d%d%d", &n, &m, &st, &ed);
for(int i=0;i<n;i++){
scanf("%d", &weight[i]);
}
for(int i=0;i<m;i++){
int begin_, end_;
scanf("%d%d", &begin_, &end_);
scanf("%d", &G[begin_][end_]);
G[end_][begin_] = G[begin_][end_];
}
Dijkstra(st);
printf("%d %d\n", num[ed], w[ed]);
return 0;
}