判断负环模板
判断负环模板
Bellman_ford \(\mathcal{O}(nm)\)
struct Bellman_ford {
using i64 = long long;
using PII = pair<i64, i64>;
int n;
vector<i64> dis;
vector<array<int, 3>> edge;
Bellman_ford(int n): n(n) {
dis.resize(n + 1, INT_MAX);
}
void add(int u, int v, int w) {
edge.push_back({u, v, w});
}
bool ok(int x) {
dis[x] = 0;
for (int i = 1 ; i < n; i ++) {
for (auto [u, v, w] : edge) {
//从顶点x出发是否能到达的负环
//若只判断图是否存在负环,则去掉上下的if...INT_MAX
if (dis[u] != INT_MAX)
dis[v] = min(dis[v], dis[u] + w);
}
}
for (auto [u, v, w] : edge) {
if (dis[u] == INT_MAX || dis[v] == INT_MAX)
continue;
if (dis[v] > dis[u] + w) {
return true;
}
}
return false;
}
};
SPFA \(\mathcal{O}(kn)\),最坏\(\mathcal{O}(nm)\)
DFS-SPFA判断负环很快\(\mathcal{O}(n^2)\),求解慢于BFS-SPFA;
struct SPFA {
using i64 = long long;
using PII = pair<i64, i64>;
vector<i64> dis, cnt;
vector<bool> vis;
vector<vector<PII>> g;
int n;
SPFA(int n): n(n) {
dis.resize(n + 1, INT_MAX);
cnt.resize(n + 1);
vis.resize(n + 1);
g.resize(n + 1);
}
void add(int u, int v, int w) {
g[u].push_back({v, w});
}
bool ok(int x) {
queue<int> Q;
Q.push(x);
dis[x] = 0, vis[x] = 1;
while (Q.size()) {
auto u = Q.front();
Q.pop();
vis[u] = 0;
for (auto [v, w] : g[u]) {
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
if (!vis[v]) {
if (++cnt[v] > n)
return true;
Q.push(v);
vis[v] = 1;
}
}
}
}
return false;
}
bool dfs_spfa(int u) {
vis[u] = 1;
for (auto [v, w] : g[u]) {
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
if (vis[v] || dfs_spfa(v))
return true;
}
}
vis[u] = 0;
return false;
}
};