模板整理: 图论---最短路


最短路……基础但重要……
主要有floyd,dijkstra,SPFA这种,
看数据范围的。
floyd还可以用来求传递闭包,也就是连通性的问题。

最短路问题:给出一张图,求s~t的最短路。
1.floyd算法。
使用它的时候一般都是用邻接矩阵计算了……

//dis[i][j]一开始的初值:
//若输入的边里有(i,j),则dis[i][j]为其权值
//不然dis[i][j]=INF
for (int k=1;k<=n;k++)
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);


……注意了有个问题就是如果初始化的值过大,
然后dis[i][k]和dis[k][j]都为INF,
INF过大……两个相加……就会爆辣!
所以初值要么不要太大,要么更新的时候判断一下。

2.dijkstra算法+堆优化
……最稳的最短路算法了。
优化一下找最小dis的过程,用堆维护,
C++STL轻松= v =
如果堆加上映射,也就是增加删除操作会更快。
多用用它吧!

//head,E都是边表(链表)的部分……
//stl大法好(可怜P党QAQ)
struct Heap{int num,val;};
priority_queue<Heap,vector<Heap> >Q;
bool operator <(Heap x,Heap y){return x.val>y.val;}
bool operator >(Heap x,Heap y){return x.val<y.val;}

void dijkstra(int s,int t){
    memset(vis,0,sizeof(vis));
    memset(dist,100,sizeof(dist));
    dist[s]=0;
    Q.push((Heap){s,0});
    while ((!Q.empty())){
        Heap mi=Q.top();Q.pop();
        if (vis[mi.num]) continue;
        vis[mi.num]=1;
        for (int j=head[mi.num];j;j=E[j].next){
            int q=E[j].to;
            if (vis[q]) continue;
            if (E[j].val+mi.val<dist[q]){
                dist[q]=E[j].val+mi.val;
                Q.push((Heap){q,dist[q]});
            }
        }
    }
}


3.SPFA算法
性价比很高,好写好记而且一般都挺快,实质是BE优化。
菊花图(就是那种发散的图),或者网格图之类的会被卡。
思路……就是暴力广搜松弛啦,好像O(m)左右(一般情况)

//这里用了循环队列,循环长度是M
int SPFA(int sta,int end){
    memset(vis,0,sizeof(vis));
    memset(dis,60,sizeof(dis));
    int h=0,tail=1;
    Q[0]=sta; dis[sta]=0;
    while (h!=tail){
        int u=Q[h];
        h=(h+1)%M;
        vis[u]=0;
        for (int i=head[u];i;i=E[i].next)
            if (dis[u]+E[i].val<dis[E[i].to]){
                dis[E[i].to]=dis[u]+E[i].val;
                if (!vis[E[i].to]){
                    vis[E[i].to]=1; 
                    Q[tail]=E[i].to;
                    tail=(tail+1)%M;
                }
            }
    }
    return dis[end];
}


注意了,以上的模板里面有初始化,
因为我懒(划掉(lll¬ω¬))所以用了memset,
实际问题中要注意初始化初值的大小也是很重要的!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值