关于最短路、负环、差分约束系统的一点笔记
关于最短路、负环、差分约束系统的一点笔记
最短路
“可以”没有环,最多\(|V|-1\)条边
有负环则不存在最短路
会形成最短路径树
算法
- Dijkstra 贪心,当\(d_u\)是最小时要满足之后\(d_u\)不会更小,不能处理负权边
- Bellman-Ford 迭代n-1轮,用边松弛
- spfa 队列优化的Bellman-Ford
最短路的线性规划形式
最大化 \(d_i\)
满足
- 三角不等式 $d_v \le d_u + w(u,v),\ $
- \(d_s=0\)
说明:上述约束对应了无穷组解。最短路求的是满足约束的最大值。因为三角不等式要求取等号时w(u,v)是最短路上的边。
应用
差分约束系统
非DAG上DP
一般使用spfa或者缩点后dp
应为dijkstra有贪心策略的限制
负环
将所有点入队,且\(d_i=0\)
负环只看不等约束,不看初始值
算法
- Bellman-Ford 常数小
- spfa 判断 1. 入队次数>=n 2.最短路长度>=n
- spfa-dfs 没多大意思,轻松被卡
应用
01分数规划
代码
见最后
差分约束系统
和最短路的线性规划形式类似的一类线性规划问题
也是需要初值的,对应d[s]=0
最短路
最大化
有负环则无解
图不连通 无关 任意解
最长路
最小化
有正环则无解
图不连通 无关 任意解
当然也可以转化成最短路
附录:
判负环的代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 2005, M = 3005;
inline int read() {
int x = 0, f = 1; char c = getchar();
while(c<'0' || c>'9') {if(c=='-') f=-1; c=getchar();}
while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
return x * f;
}
int n, m;
struct edge {int v, ne, w, u;} e[M<<1];
int cnt, h[N];
inline void ins(int u, int v, int w) {
e[++cnt] = (edge) {v, h[u], w, u}; h[u] = cnt;
}
int d[N], cou[N];
bool bellman_ford() {
for(int i=1; i<=n; i++) d[i] = cou[i] = 0;
for(int i=1; i<=n; i++) {
for(int i=1; i<=cnt; i++) {
int u = e[i].u, v = e[i].v; //printf("hi %d %d %d %d\n", u, v, d[u], d[v]);
if(d[v] > d[u] + e[i].w) {
d[v] = d[u] + e[i].w;
cou[v] = cou[u] + 1;
if(cou[v] >= n) return false;
if(i == n) return false;
}
}
}
return true;
}
int main() {
freopen("in", "r", stdin);
int T = read();
while(T--) {
cnt = 0; memset(h, 0, sizeof(h));
n = read(); m = read();
for(int i=1; i<=m; i++) {
int u = read(), v = read(), w = read();
if(w < 0) ins(u, v, w);
else ins(u, v, w), ins(v, u, w);
}
puts(bellman_ford() ? "N0" : "YE5");
}
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 2005, M = 3005;
inline int read() {
int x = 0, f = 1; char c = getchar();
while(c<'0' || c>'9') {if(c=='-') f=-1; c=getchar();}
while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
return x * f;
}
int n, m;
struct edge {int v, ne, w;} e[M<<1];
int cnt, h[N];
inline void ins(int u, int v, int w) {
e[++cnt] = (edge) {v, h[u], w}; h[u] = cnt;
}
int d[N], cou[N], inq[N], cinq[N];
int q[N], head, tail;
inline void lop(int &x) {if(x==N) x=1;}
bool spfa() {
head = tail = 1;
for(int i=1; i<=n; i++) d[i] = cou[i] = 0, inq[i] = cinq[i] = 1, q[tail++] = i;
while(head != tail) {
int u = q[head++]; lop(head); inq[u] = 0;
for(int i=h[u]; i; i=e[i].ne) {
int v = e[i].v;
if(d[v] > d[u] + e[i].w) {
d[v] = d[u] + e[i].w;
cou[v] = cou[u] + 1;
if(cou[v] >= n) return false;
if(!inq[v]) {
q[tail++] = v; lop(tail); inq[v] = 1;
if(++cinq[v] >= n) return false;
}
}
}
}
return true;
}
int main() {
freopen("in", "r", stdin);
int T = read();
while(T--) {
cnt = 0; memset(h, 0, sizeof(h));
n = read(); m = read();
for(int i=1; i<=m; i++) {
int u = read(), v = read(), w = read();
if(w < 0) ins(u, v, w);
else ins(u, v, w), ins(v, u, w);
}
puts(spfa() ? "N0" : "YE5");
}
}
Copyright:http://www.cnblogs.com/candy99/