【ACM】带权有向图单源最短路径(Dijkstra算法)

最短路径的第一类问题
求从单个源点到其余各顶点的最短路径。这是一种贪心策略,不可以存在负权边。

算法简介
给定带权有向图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];
        }
    }
}

你可能感兴趣的:(ACM)