最短路模板总结(不定时更新)

我用的是邻接表构图。

一,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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值