最短路径
Dijkstra算法模版,如果不需要输出步骤,只需删除searchPath()函数即可
不适合于有负圈的计算
可以使用priority_queue的优先队列进行排序方便查找,节省时间
#include <iostream>
#include <fstream>
#include <stdio.h>
using namespacestd;
const int maxnum =100;
const int maxint =999999;
int i,j;
void Dijkstra(int n,int v, int *dist,int *prev, int c[maxnum][maxnum])
{
bool s[maxnum]; // 判断是否已存入该点到S集合中
for(int i=1; i<=n; i++)
{
dist[i] = c[v][i];
s[i] = 0; // 初始都未用过该点
if(dist[i] ==maxint)
prev[i] = 0;
else
prev[i] = v;
}
dist[v] = 0;
s[v] = 1;
// 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
// 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
for(i=2;i<=n; i++)
{
int tmp =maxint;
int u = v;
// 找出当前未使用的点j的dist[j]最小值
for(int j=1; j<=n; j++)
if((!s[j]) && dist[j]<tmp)
{
u = j; // u保存当前邻接点中距离最小的点的号码
tmp = dist[j];
}
s[u] = 1; // 表示u点已存入S集合中
// 更新dist
for(j=1;j<=n; j++)
if((!s[j]) && c[u][j]<maxint)
{
int newdist = dist[u] + c[u][j];
if(newdist < dist[j])
{
dist[j] = newdist;
prev[j] = u;
}
}
}
}
void searchPath(int *prev,int v,int u)
{
int que[maxnum];
int tot =1;
que[tot] = u;
tot++;
int tmp = prev[u];
while(tmp != v)
{
que[tot] = tmp;
tot++;
tmp = prev[tmp];
}
que[tot] = v;
for(int i=tot; i>=1; i--)
if(i !=1)
cout << que[i] <<" -> ";
else
cout << que[i] <<endl;
}
int main()
{
//freopen("input.txt", "r", stdin);
// 各数组都从下标1开始
int dist[maxnum]; // 表示当前点到源点的最短路径长度
int prev[maxnum]; // 记录当前点的前一个结点
int c[maxnum][maxnum]; // 记录图的两点间路径长度
int n, line; // 图的结点数和路径数
// 输入结点数
cin >> n;
// 输入路径数
cin >> line;
int p, q, len; // 输入p, q两点及其路径长度
// 初始化c[][]为maxint
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
c[i][j] = maxint;
for(i=1;i<=line; i++)
{
cin >> p >> q >> len;
if(len < c[p][q]) // 有重边
{
c[p][q] = len; // p指向q
c[q][p] = len; // q指向p,这样表示无向图
}
}
for(i=1;i<=n; i++)
dist[i] =maxint;
Dijkstra(n,1, dist, prev, c);
// 最短路径长度
cout <<"源点到最后一个顶点的最短路径长度: " << dist[n] <<endl;
// 路径
cout <<"源点到最后一个顶点的路径为: ";
searchPath(prev,1, n);
return0;
}
测试数据:
输入:
5
7
1 2 10
1 4 30
1 5 100
2 3 50
3 510
4 320
4 560
输出:
Bellman-Ford 算法,可判断是否存在负圈
代码可计算有向图,输出到每个点的最短路径
#include<iostream>
#include<cstdio>
using namespacestd;
#define MAX 0x3f3f3f3f
#define N 1010
int nodenum, edgenum, original;//点,边,起点
typedef struct Edge//边
{
int u, v;
int cost;
}Edge;
Edge edge[N];
int dis[N], pre[N];
bool Bellman_Ford()
{
for(int i =1; i <= nodenum; ++i)//初始化
dis[i] = (i ==original ? 0 :MAX);
for(int i =1; i <= nodenum -1; ++i)
for(int j =1; j <= edgenum; ++j)
if(dis[edge[j].v] > dis[edge[j].u] +edge[j].cost)//松弛(顺序一定不能反~)
{
dis[edge[j].v] =dis[edge[j].u] +edge[j].cost;
pre[edge[j].v] =edge[j].u;
}
bool flag =1; //判断是否含有负权回路
for(int i =1; i <= edgenum; ++i)
if(dis[edge[i].v] > dis[edge[i].u] +edge[i].cost)
{
flag = 0;
break;
}
return flag;
}
void print_path(int root)//打印最短路的路径(反向)
{
while(root !=pre[root]) //前驱
{
printf("%d-->", root);
root = pre[root];
}
if(root ==pre[root])
printf("%d\n", root);
}
int main()
{
scanf("%d%d%d", &nodenum, &edgenum, &original);
pre[original] =original;
for(int i =1; i <= edgenum; ++i)
{
scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].cost);
}
if(Bellman_Ford())
for(int i =1; i <= nodenum; ++i)//每个点最短路
{
printf("%d\n",dis[i]);
printf("Path:");
print_path(i);
}
else
printf("have negative circle\n");
return0;
}
测试数据:
输入:
4 6 1
1 2 2
1 3 5
4 1 10
2 4 4
4 2 4
3 4 2
输出:
0
Path:1
2
Path:2-->1
5
Path:3-->1
6
Path:4-->2-->1
输入:
4 6 1
1 2 20
1 3 5
4 1 -200
2 4 4
4 2 4
3 4 2
输出:
have negative circle