最短路有很多算法:
现在我就对 Dijkstra 和 floyd 这两种算法讲一下;
这两种方法输出最短路径的时候都是利用pre数组,倒查的方法。
Dijkstra 是可以知道各个点到源点的最短距离的,是一个 dist [ ]数组记录的,时间复杂度为O(n^2);
具体实现如下:
将图中所有的顶点V分成两个集合Va,Vb,如果源点到u的最短路径已经确定,则点u属于集合Va,否则属于Vb,
在所有属于Vb的点中找一个S到其路径长度最短的点u,将u从Vb中除去,加入到Va中,
由新确定的u更新S到Vb中每一点v的距离,如果s到u的距离加上u到v的直接距离小于当前s到v的距离,表明新生成的最短路径的长度要比前面计算的要短,那么更新这个距离;
重复这个操作,知道Vb中已经没有了点或者Vb中的点都不能由源点S到达。
Floyd 是可以求出各个点到各个点的最短距离的,复杂度是O(n^3),利用了动态规划。用一个dist [ ]数组记录i到j的最短距离。
k从1到n循环n次,每次循环中,枚举图中不同的两个点u,v,如果dist[u][v] > dist[u][k] + dist[k ][v],则更新dist [u][v] = dist[u][k] + dist[k][v],pre[u][v] = pre[k][v];
具体代码:
hdu2544最短路
Dijkstra:
#include
using namespace std;
const int maxn = 10000 + 10;
int maze[maxn][maxn];
int n,m;
int dist[maxn];//记录源点s到节点i的最短距离
int pre[maxn];//记录前驱,便于打印路径
void Dijkstra(int s)
{
bool p[maxn];//记录该点是否属于Va,不属于Va的就是Vb
for(int i = 1;i <= n;i++)
{
if(i != s)
{
p[i] = false;
dist[i] = maze[s][i];
pre[i] = s;
}
}
dist[s] = 0;
pre[s] = s;
p[s] = true;
for(int i= 1 ;i<= n-1 ;i++)//对Vb中的n-1个点进行操作
{
int mins = INT_MAX;//在所有属于Vb中的点找一个S到其路径最短的点k
int k = 0;
for(int j = 1;j <= n;j++)
{
if(!p[j] && dist[j]
Floyd:
#include
using namespace std;
const int maxn = 100+ 10;
int maze[maxn][maxn];
int dist[maxn][maxn];
int n,m;
int pre[maxn][maxn];
void Floyd()
{
for(int i=1;i<=n;i++)
{
for(int j = 1;j<= n;j++)
{
dist[i][j] = maze[i][j];
pre[i][j] = i;
}
}
for(int k = 1; k<= n ;k++)
{
for(int i=1;i <= n ;i++)
{
for(int j=1 ;j<= n;j++)
{
if(dist[i][j] >= dist[i][k] + dist[k][j])
{
dist[i][j] = dist[i][k] + dist[k][j];
pre[i][j] = pre[k][j];
}
}
}
}
}
int main()
{
while(~ scanf("%d%d",&n,&m) &&(n || m))
{
memset(dist,INT_MAX,sizeof(dist));
for(int ii =1; ii <= m;ii++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
maze[x][y] = z;
maze[y][x] = z;
}
Floyd();
cout<
POJ1797 Hesvy Tansport
这个题就是找到从源点1到n的能传输的最大的重量;每条路都有一个额定最大的承重;
思路:利用 DIjstra,找到源点到每个点的最大承重。
#include
#include
#include
#include
using namespace std;
const int maxn = 1000 + 10;
int maze[maxn][maxn];
int dist[maxn];//源点到各个点的最大承重
int n,m;
void Dijkstra()
{
bool p[maxn];//Va集合
int s = 1;//源点
for(int i = 1;i <=n ;i++)
{
if(i != s)
{
p[i] = false;
dist[i] = maze[s][i];
}
}
p[s] = true;
dist[s] = INT_MAX;
for(int i = 1;i <= n-1 ;i++)
{
int maxs = 0;
int k =0;
for(int j=1 ;j<= n;j++)//在Vb中找到与源点相连的最大的承重
{
if(!p[j] && dist[j] > maxs)
{
maxs = dist[j];
k =j;
}
}
if(k == 0)
return ;
p[k] = true;
for(int j = 1; j <= n; j ++)
{
if(! p[j] && min(dist[k] , maze[k][j]) > dist[j])//比较是否通过这个路更加可行
{
dist[j] = min(dist[k],maze[k][j]);
}
}
}
}
int main()
{
int Tcase;
scanf("%d",&Tcase);
for(int ii = 1; ii <= Tcase; ii ++)
{
scanf("%d%d",&n,&m);
memset(dist,0,sizeof(dist));//承重初始化为0
memset(maze,0,sizeof(maze));//从i到j不可达的承重的就是0
for(int i =0 ;i