#include<bits/stdc++.h> constint N=100010; // 点数 structEdge { int u, v, w; booloperator<(const Edge &a) const { return w<a.w; } }; intmain(){ int n, m; std::vector<Edge>e; std::bitset<N>vis; vis.reset(); auto find_edge=[&](int u, int v)->bool { for (auto it:e) if (it.u==u&&it.v==v) returntrue; returnfalse; }; auto dfs=[&](auto self, int u)->void { if (vis[u]==1) return; vis[u]=1; for (auto it:e) if (it.u==u) self(self, it.v); }; return0; }
intmain(){ int n, m; cin >> n >> m; std::vector<std::vector<int>>adj(n + 1); std::bitset<100010>vis; vis.reset(); for (int i=1; i<=m; i++) { int u, v; std::cin>>u>>v; adj[u].push_back(v); } auto find_edge=[&](int u, int v)->bool { for (auto it:adj[u]) if (it==v) returntrue; returnfalse; }; auto dfs=[&](auto self, int u)->void { vis[u]==1; for (auto it:adj[u]) if (vis[it]==0) self(self, it); }; return0; }
intmain(){ std::vector<std::pair<int, int>>e[N]; int dis[N]; memset(dis, 0x7f, sizeof(dis)); int n, m, s; std::cin >> n >> m >> s; for (int i = 1; i <= m; i++) { int u, v, w; std::cin >> u >> v >> w; e[u].push_back({v, w}); } dis[s] = 0; bool flag = false; for (int i = 1; i < n; i++) { // 数据保证的情况下做n-1轮就可以了 flag = false; for (int j = 1; j <= n; j++) { for (auto it : e[j]) { int to = it.first, val = it.second; if (dis[to] > dis[j] + val) dis[to] = dis[j] + val, flag = true; } } if (!flag) break; } for (int i = 1; i <= n; i++) std::cout << dis[i] << ' '; return0; }
判负环
如果松弛次数$\geq n$ 那么就会有一个负环包含在图里面
到n轮还没停下来那么可以判断从当前源点出发是达到一个负环的
#include<bits/stdc++.h> intmain(){ int T, n, m; std::cin >> T; int dis[2005]; std::vector <std::pair<int, int>> e[2010]; auto Bellman_Ford = [&]() -> bool { dis[1] = 0; bool flag; for (int i = 1; i <= n; i++) { flag = false; for (int u = 1; u <= n; u++) { if (dis[u] == 0x7fffffff) continue; // 如果当前这个点不能到 也就不能松弛 for (auto eg : e[u]) { int v = eg.first, w = eg.second; if (dis[v] > dis[u] + w) dis[v] = dis[u] + w, flag = true; } } if (!flag) break; } return flag; }; while (T--) { std::cin >> n >> m; for (int i=1;i<=n;i++) dis[i]=0x7fffffff; for (int i = 1; i <= n; i++) e[i].clear(); for (int i = 1; i <= m; i++) { int u, v, w; std::cin >> u >> v >> w; if (w >= 0) e[u].push_back({v, w}), e[v].push_back({u, w}); else e[u].push_back({v, w}); } if (Bellman_Ford()) puts("YES"); else puts("NO"); } return0; }
SPFA
流程
还是依赖松弛操作 有一源点s s入队
取出队头u 找出所有的($u, v$) 尝试松弛 能被松弛的点才能入队
这样就只访问了必要的边
intmain(){ int n, m, s; std::cin >> n >> m >> s; std::bitset<100010>vis; std::vector dis(n + 1, 0x7fffffff); std::vector <std::vector<std::pair<int, int>>> e(n + 1); dis[s] = 0; vis.reset(); std::queue <int> q; q.push(s); for (int i = 1; i <= m; i++) { int u, v, w; std::cin >> u >> v >> w; e[u].push_back({v, w}); }
while (!q.empty()) { int u = q.front(); vis[u] = 0; q.pop(); for (auto eg : e[u]) { int v = eg.first, w = eg.second; if (dis[v] > dis[u] + w) { dis[v] = dis[u] + w; if (vis[v] == 0) { vis[v] = true; q.push(v); } } } }
for (int i = 1; i <= n; i++) std::cout << dis[i] << ' '; return0; }
std::bitset <2010> vis; std::vector <Edge> e[2010]; std::queue <int> q; int T, n, m, dis[2010], cnt[2010];
intmain(){ std::cin >> T; auto SPFA = [&]() -> bool { for (int i = 1; i <= n; i++) dis[i] = 0x7fffffff, cnt[i] = 0; dis[1] = 0; vis[1] = true; q.push(1); while (!q.empty()) { int u = q.front(); q.pop(), vis[u] = 0; for (auto ed : e[u]) { int v = ed.v, w = ed.w; if (dis[v] > dis[u] + w) { dis[v] = dis[u] + w; cnt[v] = cnt[u] + 1; if (cnt[v] >= n) returnfalse; if (!vis[v]) vis[v] = 1, q.push(v); } } } returntrue; }; while (T--) { while (!q.empty()) q.pop(); vis.reset(); std::cin >> n >> m; for (int i = 1; i <= n; i++) e[i].clear(); for (int i = 1; i <= m; i++) { int u, v, w; std::cin >> u >> v >> w; if (w >= 0) e[u].push_back({v, w}), e[v].push_back({u, w}); else e[u].push_back({v, w}); } if (SPFA()) puts("NO"); else puts("YES"); } return0; }
for (int i = 0; i < m; i++) { int u, v, w; std::cin >> u >> v >> w; adj[u].push_back({v, w}); }
dis[s] = 0; int curr = s, Min = 0x7fffffff; while (vis[curr] == 0) { vis[curr] = 1; for (auto it : adj[curr]) { int to = it.first, val = it.second; if (vis[to] == 0 && dis[to] > dis[curr] + val) dis[to] = dis[curr] + val; } Min = 0x7fffffff; for (int i = 1; i <= n; i++) if (dis[i] < Min && vis[i] == 0) Min = dis[i], curr = i; }
for (int i = 1; i <= n; i++) std::cout << dis[i] << ' '; return0; }
structNode { int u, w; booloperator<(const Node &a) const { return w > a.w; } };
intmain(){ int n, m, s; std::cin >> n >> m >> s; std::priority_queue <Node> q; std::vector <std::vector<std::pair<int, int>>> e(n + 1); std::vector dis(n + 1, 0x7fffffff); for (int i = 1; i <= m; i++) { int u, v, w; std::cin >> u >> v >> w; e[u].push_back({v, w}); }
q.push({s, 0}); dis[s] = 0; while (!q.empty()) { int u = q.top().u, w = q.top().w; q.pop(); if (w != dis[u]) continue; for (auto eg : e[u]) { int v = eg.first, val = eg.second; if (dis[v] > val + dis[u]) dis[v] = dis[u] + val, q.push({v, dis[v]}); } }
for (int i = 1; i <= n; i++) std::cout << dis[i] << ' ';
voidmark(int p, int l, int r, int u, int w){ // 点修 和权值树的部分一样 if (l == r) { seg[p].w = w; return; } if (u <= mid) mark(ls, l, mid, u, w); elsemark(rs, mid + 1, r, u, w); if (seg[ls].w < seg[rs].w) seg[p] = seg[ls]; else seg[p] = seg[rs]; }
intmain(){ int n, m, s, u, v, w; std::cin >> n >> m >> s; build(1, 1, n); std::vector <std::vector<std::pair<int, int>>> e(n + 1); std::vector dis(n + 1, INT_MAX); for (int i = 1; i <= m; i++) { std::cin >> u >> v >> w; e[u].push_back({v, w}); } dis[s] = 0; mark(1, 1, n, s, 0); while (seg[1].w != INT_MAX) { // 最近的节点没有被更新过 int u = seg[1].u; mark(1, 1, n, u, INT_MAX); // 等价于队列里面pop这个节点 for (auto eg : e[u]) { int v = eg.first, w = eg.second; if (dis[v] > dis[u] + w) { dis[v] = dis[u] + w; mark(1, 1, n, v, dis[v]); } } } for (int i = 1; i <= n; i++) { std::cout << dis[i] << ' '; } return0; }
/* P1144 最短路计数 */ #include<bits/stdc++.h> #define ls p << 1 #define rs p << 1 | 1 #define fi first #define se second #define mid (l + r >> 1) #define mod 100003 #define N 2010 usingnamespace std;
int mp[N][N];
structNode { int u, w; booloperator<(const Node &a) const { return w < a.w; } } seg[N << 2];
voidbuild(int p, int l, int r){ if (l == r) { seg[p] = {l, INT_MAX}; return; } build(ls, l, mid); build(rs, mid + 1, r); seg[p] = seg[ls]; }
voidmark(int p, int l, int r, int u, int w){ if (l == r) { seg[p].w = w; return; } if (u <= mid) mark(ls, l, mid, u, w); elsemark(rs, mid + 1, r, u, w); if (seg[ls].w < seg[rs].w) seg[p] = seg[ls]; else seg[p] = seg[rs]; }
intmain(){ int n, m; cin >> n >> m; vector dp(n + 1, 0); vector dis(n + 1, INT_MAX); for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) mp[i][j] = INT_MAX;
for (int i = 1; i <= m; i++) { int u, v, w; cin >> u >> v >> w; mp[u][v] = min(mp[u][v], w); }