初始:
G[][]:两点间距离
V[][]:边权
w[]:点权
dijkstra生成:
d[]:到原点的最短距离
pre[vector<int>]:当前节点在最短路径上的前驱
DFS:
遍历当前节点的所有上一个前驱节点,判断他们边权和点权的最优值生成一条最优的路径
#include <cstdio>
const int MAXV = 1000;
const int INF = 1000000000;
int n, G[MAXV][MAXV], d[MAXV], optValue;
bool vis[MAXV];
vector<int> pre[MAXV], tempPath, path;
void Dijkstra(int s) {
fill(d, d+MAXV, INF);
d[s] = 0;
// 遍历所有节点
for(int i=0; i<n; i++) {
// 寻找未访问过的d[u]最小的中间点u
int u = -1, MIN = INF;
for(int j=0; j<n; j++) {
if(vis[j] == false && d[j] < MIN) {
u = j;
MIN = d[j];
}
}
if(u == -1) return;
vis[u] = true;
// 以u为中间点,为与u相连的所有v的d赋值
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]; //更新
pre[v].clear();
pre[v].push_back(u);
} else if(d[u] + G[u][v] == d[v]) {
pre[v].push_back(u);
}
}
}
}
}
void DFS(int v) {
if(v == st) {
tempPath.push_back(v); ///
int value = 0;
//求边权和
for(int i=tempPath.size()-1; i>=0; i++) {//tempPath路径是倒的
int id = tempPath[i], idNext = tempPath[i-1];
value += V[id][idNext];
}
//求点权和
for(int i=tempPath.size()-1; i>=0; i++) {
int id = tempPath[i];
value += w[id];
}
//求对短路条数
// 既可以按之前的方法: 在Dijkstra中添加数组num[](即起点到u的最短路条数为num[u],注意是数组:下标为u,元素为源点到u的最短路条数);
// 也可以: 开一个全局变量来记录对短路的条数,当DFS到达叶子节点st时,全局变量++ 。
if(value优于optValue) {
optValue = value;
path = tempPath;
}
tempPath.pop_back(); ///
}
tempPath.push_back(v); ///
for(int i=0; i<prte[v].size(); i++) {
DFS(pre[v][i]);
}
tempPath.pop_back(); ///
}
int main() {
fill(G[0], G[0]+MAXV, INF);
//读入
Dijkstra(起点);
DFS(终点);
//输出
return 0;
}