首页 > 其他 > 详细

[模板] 最短路/差分约束

时间:2019-02-24 20:25:00      阅读:146      评论:0      收藏:0      [点我收藏+]

最短路

SPFA

时间复杂度 \(O(nm)\), 空间复杂度 \(O(n)\).

STL队列.

ll dis[nsz];
int vi[nsz],cnt[nsz];
queue<int> qu;
bool spfa(int s)
{
    rep(i,1,n)vi[i]=0,dis[i]=ninf;
    qu.push(s),dis[s]=0,vi[s]=1;
    int u;
    while(!qu.empty()){
        u=qu.front(),qu.pop(),vi[u]=0;
        forg(u,i,v){
            if(dis[v]>dis[u]+edge[i].v){
                dis[v]=dis[u]+edge[i].v;
                cnt[v]=cnt[u]+1;
                if(cnt[v]>=n)return 0; //no solution
                if(vi[v]==0){
                    qu.push(v),vi[v]=1;
                }
            }
        }
    }
    return 1;
}

手写队列.

亲测比STL慢, 似乎大量的时间浪费在取模上...==

//graph
const int nsz=1e4+50,msz=500050;
ll ninf=1e17;
int n,m,s;

struct te{int t,v,pr;}edge[msz<<1];
int hd[nsz],pe=1;
void adde(int f,int t,int v){edge[++pe]=(te){t,v,hd[f]};hd[f]=pe;}
#define forg(p,i,v) for(int i=hd[p],v=edge[i].t;i;i=edge[i].pr,v=edge[i].t)

//spfa
ll dis[nsz];
int vi[nsz],cnt[nsz];
int que[nsz],qh=1,qt=0;
int qfront(){return que[qh%n];}
void qpush(int v){que[(++qt)%n]=v;}
bool spfa(int s)
{
    rep(i,1,n)vi[i]=0,dis[i]=ninf;
    qpush(s),dis[s]=0,vi[s]=1;
    int u;
    while(qh<=qt){
        u=qfront(),++qh,vi[u]=0;
        forg(u,i,v){
            if(dis[v]>dis[u]+edge[i].v){
                dis[v]=dis[u]+edge[i].v;
                cnt[v]=cnt[u]+1;
                if(cnt[v]>=n)return 0;
                if(vi[v]==0){
                    qpush(v),vi[v]=1;
                }
            }
        }
    }
    return 1;
}

Dijkstra

时间复杂度 \(O((n+m)\log n)\).

ll dis[nsz];
int vi[nsz];
struct tdis{int x;ll d;};
bool operator<(tdis l,tdis r){return l.d>r.d;}
void dij(){
    priority_queue<tdis> pq;
    rep(i,1,n)dis[i]=ninf,vi[i]=0;
    dis[s]=0;
    pq.push((tdis){s,0});
    while(!pq.empty()){
        int u=pq.top().x;pq.pop();
        if(vi[u])continue;
        vi[u]=1;
        for(int i=h[u],v=edge[i].t;i;i=edge[i].pr,v=edge[i].t){
            if(dis[v]>dis[u]+edge[i].d){
                dis[v]=dis[u]+edge[i].d;
                pq.push((tdis){v,dis[v]});
            }
        }
    }
}

差分约束

对于 \(x_i - x_j \le a_i\), 它等价于三角不等式 \(x_i \le x_j + a_i\).

建有向边 \((x_j, x_i)\), 边权 \(a_i\). 跑最长路即可. 也可以边权 \(-a_i\), 跑最短路.

当跑最长路时, spfa无解的充要条件是图中存在正环, 这也等价于不等式组无解.

对于其他类似的不等式, 可以转化为上述形状.

[模板] 最短路/差分约束

原文:https://www.cnblogs.com/ubospica/p/10427648.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!