判断负环模板

判断负环模板

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;
	}
};
posted @ 2024-04-28 00:51  Ke_scholar  阅读(7)  评论(0编辑  收藏  举报