从最短路到差分约束系统
-
Bellman-Ford(SPFA)
-
void spfa(int s) { memset(dis,-1,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[s]=0; q.push(s); vis[s]=1; while(!q.empty()) { int now=q.front(); vis[now]=0; for(int i=head[now];i;i=nex[i]) { if(dis[to[i]]==-1 || dis[to[i]]>dis[now]+val[i]) { dis[to[i]]=dis[now]+val[i]; if(!vis[to[i]]) { vis[to[i]]=1; q.push(to[i]); } } } } }
-
注意复杂度为O(n*m),一般别用。
-
-
Dijkstra
-
void dijkstra(int s) { for(int i=1;i<=n;i++) dis[i]=-1,vis[i]=0; dis[s]=0; q.push(nod(s,0)); while(!q.empty()) { int now=q.top().id; q.pop(); if(vis[now]) continue; vis[now]=1; for(int i=head[now];i;i=nex[i]) { if(dis[to[i]]==-1 || dis[to[i]]>dis[now]+val[i]) { dis[to[i]]=dis[now]+val[i]; q.push(nod(to[i],dis[to[i]])); } } } }
-
-
Johnson
- 一般用于求N很大的多源最短路,复杂度为o(N * M * log(n)),边权可以为负。
- 做法:
- 我们新建一个虚拟节点0。从这个点向其他所有点连一条边权为 0 的边。
- 接下来用 Bellman-Ford 算法求出从 0 号点到其他所有点的最短路,记为 hi 。
- 对每一条边,我们将边权重新设置为 w+hu-hv 。
- 以每个点为起点,跑 n 轮 Dijkstra 即可。
-
差分约束系统
- 差分约束是什么呢,差分约束就是给定一些不等式,求是否存在合法解,
- 如一群小朋友分糖,要求小朋友a的糖必须比小朋友b的糖至少多d。
- 做法
- 那如果我们设小朋友a的糖为dis[a],小朋友b的糖为dis[b],那么就有等式dis[a]>=dis[b]+d,
- 那么说明dis[a]<dis[b]+d的时候我们要把它改成满足上面的形式,那么就是最长路的形式了,
- 当dis[a]<dis[b]+d的时候,把它改成dis[a]>=dis[b]+d,如果存在正环说明可以无限次松弛,则说明无解。
- 要求dis[a]==dis[b]+d 可以转换为dis[a]<=dis[b]+d && dis[a]>=dis[b]+d
- 要求dis[a]>dis[b]+d 可以转换为dis[a]>=dis[b]+d+1