1.Floyd-Warshall算法
#include <iostream> /* 解决多源最短路径 */
#include <queue> /* 两点之间的最短路径 或 一点到其余各点的最短路径 */
#include <map>
using namespace std;
int n, m, a, b, c,inf = 99999999;
int e[10][10];
int main()
{
cin>>n>>m;//顶点,边数
for(int i=1;i<=n;i++)//初始化
for(int j=1;j<=n;j++)
if(i==j) e[i][j] = 0;
else e[i][j] = inf;
for(int i=1;i<=m;i++)//读入边
{
cin>>a>>b>>c;
e[a][b] = c;
}
for(int k=1; k<=n;k++)//核心算法
for(int i=1; i<=n;i++)
for(int j=1; j<=n;j++)//if(e[i][k] < inf && e[j][k] < inf&&e[i][j] > e[i][k] + e[k][j])
if(e[i][j] > e[i][k] + e[k][j])
e[i][j] = e[i][k] + e[k][j];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
printf("%3d",e[i][j]);
cout<<"\n";
}
return 0;
}
2.Dijkstra 算法
#include <cstdio> /* 解决单源最短路径 */
#include <iostream>
using namespace std;
int e[10][10], dis[10], v[10], n, m, a, b, c, u, mi, inf = 99999999;
int main()
{
cin>>n>>m;//顶点,边数
for(int i=1;i<=n;i++)//初始化
for(int j=1;j<=n;j++)
if(i==j) e[i][j] = 0;
else e[i][j] = inf;
for(int i=1;i<=m;i++)//读入边
{
cin>>a>>b>>c;
e[a][b] = c;
}
for(int i=1;i<=n;i++)
{
dis[i] = e[1][i];//初始化dis数组,到顶点1的距离
v[i] = 0;//初始化v数组
}
v[1] = 1;
for(int i=1;i<=n-1;i++)//核心算法
{//找到离1号最近的顶点
mi = inf;
for(int j=1;j<=n;j++)
{
if(v[j] == 0 && dis[j] < mi)
{
mi = dis[j];
u = j;
}
}
v[u] = 1;
for(int v=1;v<=n;v++)
{
if(e[u][v] < inf)
{
if(dis[v] > dis[u] + e[u][v])
dis[v] = dis[u] + e[u][v];
}
}
}
for(int i=1;i<=n;i++)
printf("%d ", dis[i]);
return 0;
}
3.Bellman-Ford 算法
#include <cstdio>
#include <iostream>
using namespace std;
int dis[10], bak[10], n, m, u[10], v[10], w[10],check, f, inf = 99999999;
int main()
{
cin>>n>>m;//顶点,边数
for(int i=1;i<=m;i++)//读入边
cin>>u[i]>>v[i]>>w[i];
for(int i=1;i<=n;i++)
dis[i] = inf;//初始化dis数组,顶点1到其余各个顶点的距离
dis[1] = 0;
for(int k=1;k<=n-1;k++)//核心算法
{
//将dis数组备份至back数组中
for(int i=1;i<=n;i++)
bak[i] = dis[i];
//进一步松弛
for(int i=1;i<=m;i++)
if(dis[v[i]] > dis[u[i]] + w[i])
dis[v[i]] = dis[u[i]] + w[i];
//松弛完毕后检测dis数组是否有更新
check = 0;
for(int i=1;i<=n;i++)
{
if(bak[i] != dis[i])
{
check = 1;
break;
}
}
if(check == 0)
break;//如果dis数组没有更新,提前退出循环结束算法
}
//检查负权回路
f = 0;
for(int i=1;i<=m;i++)
if(dis[v[i]] > dis[u[i]] + w[i])
f = 1;
if(f==1)
printf("此图有负权回路\n");
else
{ //输出
for(int i=1;i<=n; i++)
printf("%d ", dis[i]);
}
return 0;
}
4.Bellman-Ford队列优化算法
#include<cstdio>
#include<queue>
using namespace std;
queue<int> q;
int n,m;
int u[8], v[8], w[8];//大小比m的最大值大1
int first[6], nex[8]; //first比n的最大值大1, next比m的最大值大1
int dis[6],book[6], inf = 99999999;
int main()
{
scanf("%d%d", &n,&m);//顶点,边数
for(int i=1;i<=n;i++)
dis[i] = inf;//初始化dis数组,顶点1到其余各个顶点的距离
dis[1] = 0;
for(int i=1;i<=n;i++)//初始化first数组
first[i] = -1;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d", &u[i], &v[i], &w[i]);//读入每一条边
//建立链表
nex[i] = first[u[i]];
first[u[i]] = i;
}
//1号顶点入队
q.push(1);
book[1] = 1;//标志1号顶点入队
while(q.size())//队列不为空循环
{
int t = first[q.front()];//处理当前队首顶点
while(t != -1)//扫描当前顶点的所有边
{
if(dis[v[t]] > dis[u[t]] + w[t])//判断松弛是否成功
{
dis[v[t]] = dis[u[t]] + w[t];//更新顶点1到顶点v[t]的路程
if(book[v[t]] == 0)//book数组标记顶点v[t]是否在队中, 不在,将顶点v[k]加入队列
{
q.push(v[t]);//入队
book[v[t]] = 1;//标记
}
}
t = nex[t];
}
book[q.front()] = 0;
q.pop();//出队
}
for(int i=1;i<=n;i++)//输出1号点到其余各个顶点的最短路径
printf("%d ", dis[i]);
return 0;
}
测试
5 7
1 2 2
1 5 10
2 3 3
2 5 7
3 4 4
4 5 5
5 3 6 5 7
0 2 5 9 9
整理于《啊哈!算法》