最短路模板總結(不定時更新)

我用的是鄰接表構圖。

一,dijstar的優先隊列優化(附打印路勁)

const int N=1100;
int head[N],cnt;
int d[N],pre[N];
struct node
{
    int u,d;
    bool operator<(const node x)const
    {
        return x.d<d;
    }
};
struct maps
{
    int v,w,next;
}edge[N*N];
void init()
{
    cnt=0;
    memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{
    edge[cnt].v=v,edge[cnt].w=w;
    edge[cnt].next=head[u],head[u]=cnt++;
}
void dijstar(int s)
{
      //memset(pre,-1,sizeof(pre));
      memset(d,0x3f,sizeof(d));
    priority_queue<node> q;
    node cur,next;
    cur.u=s,cur.d=0;
    d[s]=0;
    q.push(cur);
    int i,u,v,w;
    while(!q.empty())
    {
        cur=q.top();
        q.pop();
        u=cur.u;
        if(d[u]!=cur.d) continue;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
        <span style="white-space:pre">	</span>  v=edge[i].v,w=edge[i].w;
            if(d[v]>d[u]+w)
            {
                d[v]=d[u]+w;
                pre[v]=u;
                next.u=v,next.d=d[v];
                q.push(next);
            }
        }
    }
}
void prpath(int s,int t)
{
    int js=0,tmp[N];
    while(t!=s)
    {
        tmp[++js]=t;
        t=pre[t];
    }
    for(int i=js;i>=1;i--)
        printf("%d->",tmp[i]);
    printf("%d\n",s);
}

 二,Bellman-Ford

int Bellman_Ford(int s)
{
    for(int i = 1; i <= n; ++i) //初始化
        d[i] = (i == s ? 0 : MAX);
    for(int i = 1; i < n ; ++i)
        for(int j = 1; j <= m; ++j)
            if(d[e[j].v] > d[e[j].u] + e[j].w) //鬆弛(順序一定不能反~)
            {
                d[e[j].v] = d[e[j].u] + e[j].w
                pre[e[j].v] = e[j].u;
            }
    int flag = 1; //判斷是否含有負權迴路
    for(int i = 1; i <= m; ++i)
        if(d[e[i].v] > d[e[i].u] + e[i].w)
        {
            flag = 0;
            break;
        }
    return flag;
}



 三,spfa(基於Bellman-Ford

SPFA算法有兩個優化算法 SLF 和 LLL: SLF:Small Label First 策略,設要加入的節點是j,隊首元素爲i,若dist(j)<dist(i),則將j插入隊首,否則插入隊尾。 LLL:Large Label Last 策略,設隊首元素爲i,隊列中所有dist值的平均值爲x,若dist(i)>x則將i插入到隊尾,查找下一元素,直到找到某一i使得dist(i)<=x,則將i出對進行鬆弛操作。 SLF 可使速度提高 15 ~ 20%;SLF + LLL 可提高約 50%。 在實際的應用中SPFA的算法時間效率不是很穩定,爲了避免最壞情況的出現,通常使用效率更加穩定的Dijkstra算法。

const int N=110;
const int M=N*N;
int d[N],p[N],cnt[N],q[M];
int head[N],js;//,pre[N];
struct node
{
    int v,w,next;
}e[M];
void add(int u,int v,int w)
{
    e[js].v=v,e[js].w=w;
    e[js].next=head[u],head[u]=js++;
}
void init()
{
      //memset(pre,-1,sizeof(pre));
      memset(head,-1,sizeof(head));
    js=0;
}
int spfa(int s,int n)
{
      memset(d,0x3f,sizeof(d));
    memset(p,0,sizeof(p));
    memset(cnt,0,sizeof(cnt));
    int u,v,w,l=0,r=0;
    q[++r]=s,d[s]=0,p[s]=1;
    while(l<r)
    {
        p[u=q[++l]]=0;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            v=e[i].v,w=e[i].w;
            if(d[v]>d[u]+w)
            {
                d[v]=d[u]+w;
                //pre[v]=u;
                if(!p[v])
                {
                    if(++cnt[v]>n)      //存在負環
                        return 0;
                    p[v]=1;
                    q[++r]=v;
                }
            }
        }
    }
    return 1;
}
void prpath(int s,int t)
{
    int js=0,tmp[N];
    while(t!=s)
    {
        tmp[++js]=t;
        t=pre[t];
    }
    for(int i=js;i>=1;i--)
        printf("%d->",tmp[i]);
    printf("%d\n",s);
}

三,全源最短路Floyd

注意: d[i][i]實際上表示「從頂點 i 繞一圈再回來的最短路徑」,因此圖存在負環當且僅當 d[i][i]<0。

int d[N][N],path[N[N],n;//path記錄路徑,d表示初始距離(若相連則初始化爲邊權,若無則爲無窮大)
int floyd()
{
    int i,j,k;
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            path[i][j]=j;
    for(k=1;k<=n;k++)
    {
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                if(d[i][k]+d[k][j]<d[i][j])
                {
                    d[i][j]=d[i][k]+d[k][j];
                    path[i][j]=path[i][k];
                    if(i==j&&d[i][j]<0)     ////存在負環
                        return 0;
                }
            }
        }
    }
    return 1;
}
void prpath(int u,int v)
{
    printf("%d->%d: \n",u,v);
    printf("%d",u);
    while(u!=v)
    {
        printf("->%d",path[u][v]);
        u=path[u][v];
    }
    printf("\n");
}




參考文章:http://www.renfei.org/blog/weighted-shortest-path.html

  http://www.haodaima.net/art/2233075

發佈了30 篇原創文章 · 獲贊 1 · 訪問量 8185
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章