[模板] 最短路/差分約束
阿新 • • 發佈:2019-02-24
手寫 最長 隊列 空間 親測 inline 其他 復雜度 line
最短路
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無解的充要條件是圖中存在正環, 這也等價於不等式組無解.
對於其他類似的不等式, 可以轉化為上述形狀.
[模板] 最短路/差分約束