注:本文采用dijkstra算法对顶点1 (编号最小的点)的最短路径长度,代码在解决问题的本质上并未用到p[]和P[][]数组,只是用来记录 。
Description |
设计算法,求出无向连通图中距离顶点1 (编号最小的点)的最短路径长度。其中图的输入序列,举例如下: 输入: 3 1 2 12 1 3 8 2 3 4 其中第一行的“3”表示图的结点数,第二行至最后一行表示边及边上的权值;其中第二行“1 2 12”表示结点1与结点2有边,其权值为2。 输出: 结点1到其余顶点(按照结点编号升序)的最短路径长度。 |
Sample Input |
4 1 2 6 1 3 4 1 4 10 2 3 3 2 4 6 3 4 1 |
Sample Output |
6 4 5 |
Hint |
输出有换行 |
#include <bits/stdc++.h>
#define Max_size 105
#define INTSIZE 32576
using namespace std;
// p[v]为从v0到其余顶点v的最短路径 D[]为其带权长度
int D[Max_size], P[Max_size];
// 邻接矩阵
typedef struct Arcell
{
int adj;
} Arcell, adjMa[Max_size][Max_size];
typedef struct
{
int vexs[Max_size];
adjMa arcs;
int vex, arc;
} MG;
void creatMG(MG &G)
{ // 创建无向连通图
int n, v1, v2, info;
cin >> n;
G.vex = n;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{ // 初始化都为最大值
G.arcs[i][j].adj = INTSIZE;
}
}
while (cin >> v1 >> v2 >> info)
{ // 包括对称点
G.arcs[v1][v2].adj = info;
G.arcs[v2][v1].adj = info;
}
}
void Shortest(MG G, int v1)
{
// p[v][w]为1表示w是从v0到v求得最短路径上的顶点
// final[]为判断是否存在回路的辅助数组 为1时当且仅当v属于S顶点集表示以求得v0到v的最短路径
int v, w, p[Max_size][Max_size], final[Max_size], i;
for (v = 1; v <= G.vex; v++)
{ // 初始化
final[v] = 0; // 没找到
D[v] = G.arcs[v1][v].adj; // 记录
for (w = 1; w <= G.vex; w++)
p[v][w] = 0; // 把所有路径设空
if (D[v] < INTSIZE)
{ // 表示有直接路径
p[v][v1] = 1;
p[v][v] = 1; // v必然是从v0到v的关键结点
}
}
D[v1] = 0;
final[v1] = 1; // 初始化v1顶点属于S集
for (i = 2; i <= G.vex; i++) // 其余n-1结点
{ // 开始求v0到每个顶点的最短路径,并加到S集
int min = INTSIZE; // 当前距离v0最近距离
for (w = 1; w <= G.vex; w++)
{
if (!final[w])
{ // 未在S中(没有回路)
if (D[w] < min)
{ // 最近的邻接点
v = w;
min = D[w];
}
}
}
final[v] = 1; // 标记加入S
for (w = 1; w <= G.vex; w++)
{
if (!final[w] && (min + G.arcs[v][w].adj < D[w]))
{ // 未在S(无回路)并且最小距离加上权值小于直达 就更新数值
D[w] = min + G.arcs[v][w].adj;
P[w] = P[v];
p[w][w] = 1; // 从v0到w标记
}
}
}
}
int main()
{
MG G;
adjMa p;
creatMG(G);
Shortest(G, 1);
int cnt = 0;
for (int w = 2; w <= G.vex; w++)
{
cout << D[w];
if (cnt != G.vex - 2)
cout << " ";
cnt++;
}
cout << "\n";
return 0;
}