三种方法:
1.dijkstra:1~各个顶点的最短路径;
2.floyd:任意两点之间的最短距离
3.bellman kord:
(1)最短路径(1~n个顶点的最短路径)
(2)判断是否含有负权回路
(1)Dijkstra
#include<iostream>
using namespace std;
const int Max=10005;
const int INF=99999999;
int mp[Max][Max];
int dis[Max],vis[Max];
void Dijkstra(int n)
{
for(int i=1;i<=n;i++)
{
dis[i]=mp[1][i];
}
int Min=INF,p;
vis[1]=1;
for(int i=1;i<n;++i)
{
Min=INF;
for(int j=1;j<=n;j++)
{
if(Min>dis[j]&&!vis[j])
{
Min=dis[j];
p=j;
}
}
vis[p]=1;
for(int k=1;k<=n;k++)
{
if(dis[k]>mp[p][k]+dis[p])
dis[k]=mp[p][k]+dis[p];
}
}
}
int main()
{
int n,m,u,v,vl,c;
cout<<"---------1. 使用已给样例-------------"<<endl;
cout<<"---------2. 手动输入 -------------"<<endl;
cin>>c;
if(c==2)
{
cout<<"输入顶点个数和弧数:"<<endl;
cin>>n>>m;
}
else
{
n=3,m=3;
}
//初始化
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;j++)
mp[i][j]=INF;
}
if(c==2)
{
cout<<"相关联点的信息:"<<endl;
for(int i=0;i<m;++i)
{
cin>>u>>v>>vl;
if(mp[u][v]>vl)
mp[u][v]=mp[v][u]=vl;//当两顶点之间的值有多个时。取最小的
}
}
else
{
mp[1][2]=mp[2][1]=1;
mp[2][3]=mp[3][2]=1;
mp[1][3]=mp[3][1]=4;
}
Dijkstra(n);
cout<<"矩阵显示"<<endl;
cout<<"------------------"<<endl;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;++j)
cout<<mp[i][j]<<" ";
cout<<endl;
}
cout<<"------------------"<<endl<<endl;
cout<<"1到各个顶点的最短路径:"<<endl;
for(int i=2;i<=n;i++)
{
cout<<1<<"-->"<<i<<":"<<dis[i]<<endl;
}
}
(2)floyd
/*
floyd:
@目的:可以得到任意两点之间的最短距离;
@注意点:
1.到自身的权值为0
2.不能到达的点为无穷
@有向性:有向图
*/
#include<iostream>
using namespace std;
const int Max=10005;
const int INF=99999999;
int mp[Max][Max];
void floyd(int n)
{
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
for(int k=1;k<=n;k++)
{
if(mp[i][j]>(mp[i][k]+mp[k][j]))
mp[i][j]=mp[i][k]+mp[k][j];
}
}
}
}
int main()
{
int n,m;
cout<<"输入顶点数,边数:"<<endl;
cin>>n>>m;
//初始化
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
if(i==j)
{
mp[i][j]=0;
continue;
}
mp[i][j]=INF;
}
}
//边信息
int u,v,w;
for(int i=1;i<=m;++i)
{
cin>>u>>v>>w;
if(mp[u][v]>w)
mp[u][v]=w;
}
cout<<"运算前:"<<endl;
cout<<"-------------------"<<endl;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
cout<<mp[i][j]<<" ";
}
cout<<endl;
}
cout<<"-------------------"<<endl;
floyd(n);
cout<<"运算后:"<<endl;
cout<<"-------------------"<<endl;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
cout<<mp[i][j]<<" ";
}
cout<<endl;
}
cout<<"-------------------"<<endl;
}
/*
input
4 8
1 2 2
1 3 6
1 4 4
2 3 3
3 1 7
3 4 1
4 1 5
4 3 12
output
0 2 5 4
10 0 3 4
6 8 0 1
5 7 10 0
*/
(3)Bellman-kord
/*
bellman-kord
作用:
(1)最短路径(1~n个顶点的最短路径)
(2)判断是否含有负权回路
*/
#include<iostream>
using namespace std;
const int Max=10005;
const int INF=99999999;
int u[Max],v[Max],w[Max];
int dis[Max<<1];
int main()
{
int n,m,check=0;
cout<<"输入顶点数和边数:"<<endl;
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]=0;
for(int i=1;i<n;i++) //松弛n-1次
{
check=0;
for(int j=1;j<=m;j++)
{
if(dis[v[j]]>dis[u[j]]+w[j])
{
dis[v[j]]=dis[u[j]]+w[j];
check=1;
}
}
if(!check) break;//若dis数组没有发生松弛,直接跳出
}
int flag=0;//检查是否含有负权回路
for(int j=1;j<=n;++j)
{
if(dis[v[j]]>dis[u[j]]+w[j])
{
flag=1;
}
}
if(flag) cout<<"存在负权回路 !"<<endl;
else
{
for(int i=1;i<=n;++i)
{
cout<<dis[i]<<" ";
}
cout<<endl;
}
return 0;
}
/*
input
5 5
2 3 2
1 2 -3
1 5 5
4 5 2
3 4 3
output
0 -3 -1 2 4
*/