【Topic】Single-source shortest path (Spfa, Dijkstra)

spfa

Spfa is a graph theory method similar to bfs, which uses the queue to update dis[i] to obtain the shortest path from 1 to n in the graph.

Dis[i] is used in Spfa to indicate the length of each point in the picture from the starting point, bz[i] is used to record whether the point numbered i is in the team, a[x,y] indicates the distance between x~y in the picture , b[x,i] represents the end point of the i-th edge of the point numbered x. Each time the distance from the end point to the starting point is updated, it is updated with the current point in the queue, and finally the answer is obtained.

tov[i] represents the end point of the edge numbered i;
next[i] represents the next edge to be searched for the edge numbered i;
last[i] represents the last edge starting with the node i;
len[i] represents The weight numbered i;

Code

#include<cstdio>
#include<cmath>;
#include<iostream>
using namespace std;
int n,m,i,next[100001],len[100001],last[10001],tov[100001],tot,head,tail,dis[10001],f[10000001];
bool bz[10001];
void insert(int x,int y,int z)
{
    tot++;
    len[tot]=z;
    tov[tot]=y;
    next[tot]=last[x];
    last[x]=tot;
}
int main()
{
    scanf("%d%d",&n,&m);
    int x,y,z;
    for (i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        insert(x,y,z);
    }
    head=0;
    tail=1;
    for (i=1;i<=n;i++)
        dis[i]=2147483647/2;
    dis[1]=0;
    bz[1]=true;
    f[1]=1;
    while (head!=tail)
    {
        head++;
        x=f[head];
        i=last[x];
        while (i!=0)
        {
            y=tov[i];
            if (dis[x]+len[i]<dis[y])
            {
                dis[y]=dis[x]+len[i];
                if (bz[y]==false)
                {
                    bz[y]=true;
                    tail++;
                    f[tail]=y;
                }
            }
            i=next[i];
        }
        bz[x]=false;
    }
    for (i=2;i<=n;i++)
    {
        if (dis[i]!=2147483647/2)
            printf("%d\n",dis[i]);
        else printf("%d\n",-1);
    }
}

Dijkstra

Dijkstra is a greedy-dominant single-source shortest path algorithm.

Find the one with the smallest dis value each time and use it to update the other points. So as to realize the single-source shortest path.

Code

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,m,next[100001],len[100001],last[10001],tov[100001],tot,head,tail,dis[10001],f[10000001];
bool bz[10001];
void insert(int x,int y,int z)
{
    len[++tot]=z;
    tov[tot]=y;
    next[tot]=last[x];
    last[x]=tot;
}
int main()
{
    scanf("%d%d",&n,&m);
    int x,y,z,i,j,k,p;
    memset(dis,127,sizeof(dis));
    for (i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        insert(x,y,z);
        if(x==1) dis[y]=min(dis[y],z);
    }
    dis[1]=0;
    bz[1]=true;
    for (i=1;i<=n;++i)
    {
        p=2147483647;
        for (j=1;j<=n;++j)
        {
            if(!bz[j]&&dis[j]<p)
            {
                p=dis[j];
                k=j;    
            }
        }   
        bz[k]=true;
        for (j=last[k];j;j=next[j])
            dis[tov[j]]=min(dis[k]+len[j],dis[tov[j]]);
    }
    for (i=2;i<=n;i++)
    {
        if (dis[i]<2147483647/2)
            printf("%d\n",dis[i]);
        else printf("%d\n",-1);
    }
}

Heap optimization:

The biggest point of Dijkstra's heap optimization is to record the position of each point in the heap, and to up that point in the heap after each update, otherwise the shape of the heap is the dis value after the update. Incorrect.

Code

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,m,tot,head,tail,dis[10001],f[10000001];
int next[100001],len[100001],last[10001],tov[100001];
int d[100010];
bool bz[10001];
int a[100010]; 
void insert(int x,int y,int z) 
{
    len[++tot]=z;
    tov[tot]=y;
    next[tot]=last[x];
    last[x]=tot;
}
void up(int x)
{
    while(x>1&&dis[d[x]]<dis[d[x/2]])
    {
        swap(d[x],d[x/2]);
        swap(a[d[x]],a[d[x/2]]);
        x/=2;
    }
}
void down(int x)
{
    int k;
    while(x*2<=tot&&dis[d[x]]>dis[d[x*2]]||x*2+1<=tot&&dis[d[x]]>dis[d[x*2+1]])
    {
        k=x*2;
        if(k+1<=tot&&dis[d[k]]>dis[d[k+1]]) k++;
        swap(d[x],d[k]);
        swap(a[d[x]],a[d[k]]);
        x=k;
    }   
}
int main()
{
    scanf("%d%d",&n,&m);
    int x,y,z,i,j,k,p;
    memset(dis,127,sizeof(dis));
    for (i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        insert(x,y,z);
        if(x==1) dis[y]=min(dis[y],z);
    }
    dis[1]=0;
    bz[1]=true;
    tot=0;
    for (i=2;i<=n;++i)
    {
        d[++tot]=i;
        a[i]=tot;
        up(tot);
    }
    for (i=1;i<=n;++i)
    {
        k=d[1];
        d[1]=d[tot],a[d[1]]=1,down(1);  
        for (j=last[k];j;j=next[j]) 
        { 
            dis[tov[j]]=min(dis[k]+len[j],dis[tov[j]]);
            up(a[tov[j]]);
        } 
    }
    for (i=2;i<=n;i++)
    {
        if (dis[i]<2147483647/2)
            printf("%d\n",dis[i]);
        else printf("%d\n",-1);
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326047700&siteId=291194637