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

最短路

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无解的充要条件是图中存在正环, 这也等价于不等式组无解.

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

posted @ 2019-02-24 20:08  Ubospica  阅读(156)  评论(0编辑  收藏  举报