最短路径的第一类问题
求从单个源点到其余各顶点的最短路径。这是一种贪心策略,不可以存在负权边。
算法简介
给定带权有向图G和源点v0,求从源点v0到G中其余各顶点的最短路径。迪杰斯特拉算法是对有权图进行搜索,但是如果引用于无权图或者是权值相等的图,就是广度优先搜索。(注意是有向图)
算法描述
对于网N=(V,E),将N中的顶点分成两组:
第一组S:已求出的最短路径的终点集合(初始时只含有v0)
第二组V-S:尚未求出最短路径的终点集合(初始时为V-{v0})
算法将按照各顶点与v0间的最短路径长度递增的次序,逐个将集合V-S中的顶点加入到集合S中。在这个过程中,总保持从v0到集合S中每一个顶点的路径长度始终不大于到集合V-S中各顶点的路径长度。
每当加入一个新的顶点到S集合中,对于V-S集合的顶点而言,多了一个中转结点
,因此要对V-S集合中的各个顶点的最短路径的长度进行更新。
算法代码
const int INF = 0x3f3f3f3f; //防止后面溢出,INF不能太大
const int maxn = 1000+5; //点的个数
bool visit[maxn]; //bool[i]表示是否确定过最短路径
int map[maxn][maxn]; //用邻接矩阵的方式来存储图
int distance[maxn]; //distance[i]表示v0到vi的最短路径
void Dijkstra(int n,int beg) //beg表示源结点
{
for(int i=1;i<=n;i++)
{
distance[i] = map[beg][i];
visit[i] = false;
}
visit[beg] = true;
distance[beg] = 0;
int v;
for(int i=2;i<=n;i++) //对其他的n-1个点进行操作
{
int Min = INF;
for(int j=1;j<=n;j++)
{
//遍历左右结点,找到离当前源点的最短路径
if(!visit[j] && distance[j] < Min)
{
v = j;
Min = distance[j];
}
}
visit[j] = true; //加入S集合
//松弛操作
for(int j=1;j<=n;j++)
{
if(!visit[j] && Min + map[v][j] < distance[j]) //利用这次加入的边的Min进行对V-S集合distance的更新
//每一次MIn是S中最大的,因为之前加入的比后来的小
distance[j] = Min + map[v][j];
}
}
}