该算法可以解决单源最短路径问题
单源指:以图中一个点作为源点,该算法用来求该源点到其他各个点的最短路径,我们代码中用dst数组记录
基本思想:
每次找到离源点最近的一个顶点u,然后再拿这个顶点u进行更新dst数组(即dst[k] = min(dst[k] , dst[u] + edge[u][k])),最终得到源点到其余所有点的最短路径
基本步骤:
一、把图中所有顶点分到俩个集合中,即最短路径的顶点集合S和未知最短路径的顶点集合Q。很显然初始时,只有源点在S集合中,其他顶点都在Q集合中。 在代码实现时,我们可以开一个bool型的数组mark,mark[i] = true表示i顶点在S集合中。mark[i] = false表示i顶点在Q集合中。
const int MAXN=1e5;
bool mark[MAXN];
memset(mark,0,sizeof mark); //除源点外,其他顶点在Q集合中
mark[1]=true; //顶点1作为源点,初始在S集合中
二、设置最短路径数组dst并不断更新:初始时:dst[i] = edge[s][i],(s为源点,edge为邻接矩阵)。dst[s] = 0, mark[s] = true. 此时在Q集合中选择一个离源点s最近的顶点u加入S集合中。
const int inf = 0x3f3f3f3f; //一个非常大的数,相当于无穷大
int u; //距离源点s最近的顶点u
int min_path = inf;
for(int j=1;j<=n;j++)
{
if(mark[j] == 0 && dst[j] < min_path) //在集合Q中选择离源点s最近的顶点
{
min_path = dast[j];
u = j;
}
mark[u] = true; //把找到的最近顶点u放到S集合中
}
然后拿新加入的顶点u进行更新dst数组,即在集合Q中找一个顶点k,如果原来顶点k到源点s的距离 > (顶点k到u的距离 + 顶点u到源点s的距离),那么更新 原来顶点k到源点s的距离 = (顶点k到u的距离 + 顶点u到源点s的距离)
for(int k=1;k<=n;k++)
{
if(edge[u][k]<inf && mark[k] == 0) // u可以到达k并且,k在集合Q中
{
if(dst[k] > dst[u] + edge[u][k]) //原来顶点k到源点s的距离 > (顶点u到源点s的距离 + u
//到k的距离)
{
dst[k] = dst[u] + edge[u][k];
//顶点k到源点s的距离 = 源点s到顶点u的距离 + u到k的距离
}
}
}
三、在集合Q中再新找一个离源点s最近的顶点u加入集合S中,重复上面操作,直到所有顶点都到集合S中。dst数组中就是源点s到其他各个顶点的最短路径
完整代码
const int inf=0x3f3f3f3f;
const int MAXN=1e3 + 1;
int edge[MAXN][MAXN];
bool mark[MAXN]; //标记顶点在哪个集合
int dst[MAXN];//最短路径数组
int s; //s代表源点
int u; //中间顶点u
fill(edge,edge + MAXN*MAXN,inf);//先初始化邻接矩阵,再输入
for(i = 1; i <= n; i++) dst[i] = edge[s][i]; //源点s到其他各个顶点距离的初始化
dst[s] = 0;
memset(mark,0,sizeof mark);
mark[s] = 1;
int min_path;
for(i = 1; i <= n-1; i++){ //初始源点已在集合S中,再放入n-1个顶点算法结束
//找到离源点最近的顶点u,称它为新中心点
min_path = inf;
for(j = 1; j <= n; j++){
if(mark[j] == 0 && dst[j] < min_path){
min_path = dst[j];
u = j;
}
}
mark[u] = 1;
//更新最短路径数组
for(k = 1; k <= n; k++){
if(edge[u][k] < inf && mark[k] == 0){
if(dst[k] > dst[u] + edge[u][k])
dst[k] = dst[u] + edge[u][k];
}
}
}