解法参考:https://blog.csdn.net/qq_43813697/article/details/89599623
题目描述
Sample Input
5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1
Sample Output
2 4
AC代码
#include <iostream>
#define MAXV 520
using namespace std;
/*静态变量区 */
const int INF = 0xffff;
/*全局变量区 */
int Adj[MAXV][MAXV]; //邻接矩阵
bool Vis[MAXV] = {false}; //是否访问过
int Dis[MAXV], //距离
W[MAXV] = {0}, //最大权重和
Num[MAXV] = {0}; //最短路径条数
int Weight[MAXV]; //权重(救援队数量)
int N,M,C1,C2; //点数,路径数,起点,终点
/*
改进的迪杰斯特拉算法
求出由源点到所有其他节点的最短路径的条数
并更新权重(救援队人数)
@param sc 源点标号
*/
void dijkstra(int sc){
Dis[sc] = 0; //到源点sc的距离为0
W[sc] = Weight[sc]; //到源点sc的权重和为sc自己的权重
Num[sc] = 1; //到源点的最短路径数量初始为1
for(int j = 0;j<N;++j){
int minD = INF;
int newV = -1;
//找到Dis中值最小的
for(int i = 0;i<N;++i){
if(!Vis[i] && Dis[i] < minD){
newV = i;
minD = Dis[i];
}
}
if(newV == -1)
return;
//将newV收入S点集
Vis[newV] = true;
//newV作为中间节点去更新 Dis
for(int i = 0;i<N;++i){
if(!Vis[i] && Adj[newV][i] != INF){
if(Dis[newV] + Adj[newV][i] < Dis[i]){
//如果经过newV点到i点的路径长度比原来短
Dis[i] = Dis[newV] + Adj[newV][i];
W[i] = W[newV] + Weight[i];
//如果到newV的最短路径条数为Num[newV]
//那么到i的最短路径条数也为Num[newV]
Num[i] = Num[newV];//重点
}else if(Dis[newV] + Adj[newV][i] == Dis[i]){
//如果经过newV点到i点的路径长度和原来一样
if(W[i]< W[newV] + Weight[i]){
//如果走这条路叫的救援队可以更多
W[i] = W[newV] + Weight[i];
}
//到i的最短路径条数要加上到newV的最短路径条数
Num[i] += Num[newV]; //重点
}
}
}
}
}
int main(){
cin>>N>>M>>C1>>C2;
for(int i = 0; i<N ;++i){
cin >> Weight[i];
}
//邻接矩阵初始默认任意两点间距离无穷大
fill(Adj[0],Adj[0]+MAXV*N,INF);
//到点集的距离初始默认无穷大
fill(Dis,Dis+N,INF);
int u,v,len;
for(int i = 0;i<M;++i){
cin>>u>>v>>len;
Adj[v][u] = Adj[u][v] = len;
}
dijkstra(C1);
cout<<Num[C2]<<' '<<W[C2];
return 0;
}
fill的使用
将一个区间的元素都赋予val值,通常可以用来初始化数组
void fill(要开始填充的数组中地址,要结束填充的数组中地址,用来填充的值)
头文件
#include <iostream>
使用fill初始化一维数组
可以根据实际需要的大小填充
int Dis[MAXV];
fill(Dis,Dis+N,INF);
使用fill初始化二维数组
由于二维数组是数组的数组,是一行一行存储的,因此如果只需要填充一部分时,需要注意在起始地址上加 n*固定列宽 。
const int INF = 0xffff;
const int MAXV = 520;
int Adj[MAXV][MAXV];
fill(Adj[0],Adj[0] + MAXV*N,INF);