(图论)Dijkstra单源最短路

这个算法适用于权值为非负的图的单源最短路径

解释以后再补充,废话不多说先模板

这是以邻接矩阵来储存的算法:

const int INF=0x3f3f3f3f;//无穷
bool vis[maxn];//判断节点是否已经被访问
ll d[maxn];//每个点到1这个点的最短距离
int way[maxn][maxn];//路径,以邻接矩阵形式
int path[maxn];//储存的路径,path[i]为由i到path[i],用while遍历
/*
最短路径path的遍历方法:
int pos=n;
while(true)
    {
        if(pos==1)break;
        //----------
        //此处添加操作
        //----------
        pos=path[pos];
    }
*/
int n;
bool once=true;
void Dijkstra()
{
    memset(vis,false,sizeof(vis));
    d[1]=0;//这里把1搞成0就是要求其它点到1的最短距离,改成其它等于零可以求到其它点的最短距离
    for(int i=2;i<=n;i++)//这里让它们初始为无穷
        d[i]=INF;
    for(int i=1;i<=n;i++)
    {
        int x,m=INF;//x离1节点最近但是没有被访问的点,m记录这个点到1的最短距离
        for(int j=1;j<=n;j++)//这里遍历来替换,得到x,m
        {
            if(!vis[j]&&d[j]<=m)
            {
                m=d[j];
                x=j;
            }
        }
        vis[x]=true;//标记已经访问
        for(int y=1;y<=n;y++)
        {
            if(way[x][y]==0)continue;//在这里,为0代表没有路,也可以初始化所有路为INF
            if(d[y]>d[x]+way[x][y])//更新被选中x相邻的点的值,确保最小
            {
                d[y]=d[x]+way[x][y];
                    path[y]=x;//储存一条最短路径,并且是倒序
            }
        }
    }
}

可以用邻接表来,有些时候会省时间:

const int INF=0x3f3f3f3f;
bool vis[maxn];
ll d[maxn];
int path[maxn];
int n;
typedef struct node
{
    int aim;//这条路的终点
    int dis;//这条路的长度
};
vector<node> way[maxn];
bool once=true;
void Dijkstra()
{
    memset(vis,false,sizeof(vis));
    d[1]=0;
    for(int i=2;i<=n;i++)
        d[i]=INF;
    for(int i=1;i<=n;i++)
    {
        int x,m=INF;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&d[j]<=m)
            {
                m=d[j];
                x=j;
            }
        }
        vis[x]=true;
        for(int j=0;j<way[x].size();j++)//不用判断路是否存在了,直接列出所有路
        {
            if(d[way[x][j].aim]>d[x]+way[x][j].dis)
            {
                d[way[x][j].aim]=d[x]+way[x][j].dis;
                path[way[x][j].aim]=x;
            }
        }
    }
}

你可能感兴趣的:((算法)(图论))