NewCodeTemplate

This commit is contained in:
e2hang
2025-12-16 20:36:27 +08:00
parent 684e35b210
commit 8253f2dcbc
26 changed files with 2547 additions and 0 deletions

View File

@@ -0,0 +1,140 @@
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = LLONG_MAX / 4; // 足够大plus 操作不会溢出
struct Edge {
int u, v;
ll w;
Edge(int _u=0, int _v=0, ll _w=0) : u(_u), v(_v), w(_w) {}
};
/*
* Bellman-Ford 竞赛模板
*
* 输入:
* n : 顶点数 (0..n-1)
* m : 边数
* 接下来 m 行,每行 u v w (表示 u -> v 的边权为 w
* s : 源点
*
* 输出(模板示例):
* 对每个顶点 i
* - 若 i 不可达: 输出 "INF"
* - 若 i 可达并且受负环影响(距离可任意减小): 输出 "-INF"
* - 否则 输出最短距离 dist[i]
*
* 另外提供 reconstruct_path(s, t, prev) 重建单源到 t 的一条最短路径(若可重建)
*
* 复杂度O(n * m)
*/
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
if (!(cin >> n >> m)) return 0;
vector<Edge> edges;
edges.reserve(m);
for (int i = 0; i < m; ++i) {
int u, v;
long long w;
cin >> u >> v >> w;
// 若输入为 1-index请在此处做 --u; --v;
edges.emplace_back(u, v, w);
}
int s;
cin >> s; // 源点
// ---------- Bellman-Ford 主体 ----------
vector<ll> dist(n, INF);
vector<int> prev(n, -1); // 用于路径重建
dist[s] = 0;
// 1) 做 n-1 轮松弛,使 dist 收敛(若无负环)
for (int iter = 0; iter < n - 1; ++iter) {
bool updated = false;
for (const auto &e : edges) {
if (dist[e.u] != INF && dist[e.v] > dist[e.u] + e.w) {
dist[e.v] = dist[e.u] + e.w;
prev[e.v] = e.u;
updated = true;
}
}
if (!updated) break; // 提前退出(常见优化)
}
// 2) 检测并标记受负环影响的节点
// nodes_in_neg_cycle[i] == true 表示 i 的距离可以无限减小
vector<char> in_neg(n, 0);
// 第 n 轮:若还能松弛则相关节点受负环影响(或者能从某个负环传播到)
// 我们先把可以被松弛的点入队,然后在图上做 BFS/DFS 向外传播(因为负环的影响会沿有向边传播到可达节点)
queue<int> q;
for (const auto &e : edges) {
if (dist[e.u] != INF && dist[e.v] > dist[e.u] + e.w) {
// e.v 受影响(直接)
if (!in_neg[e.v]) {
in_neg[e.v] = 1;
q.push(e.v);
}
}
}
// 为了传播负环影响,需要图的邻接表(从受影响节点向外传播)
vector<vector<int>> adj_out(n);
for (const auto &e : edges) {
adj_out[e.u].push_back(e.v);
}
// BFS/DFS 从初始受影响节点传播,标记所有可达顶点为受影响
while (!q.empty()) {
int x = q.front(); q.pop();
for (int y : adj_out[x]) {
if (!in_neg[y]) {
in_neg[y] = 1;
q.push(y);
}
}
}
// ---------- 输出结果示例 ----------
// 若想要标准竞赛输出:可根据题目要求调整输出格式
// 下面按通用风格输出每个顶点的状态
for (int i = 0; i < n; ++i) {
if (in_neg[i]) {
cout << "-INF"; // 受负环影响,可以任意小
} else if (dist[i] == INF) {
cout << "INF"; // 不可达
} else {
cout << dist[i]; // 有确定的最短距离
}
if (i + 1 < n) cout << ' ';
}
cout << '\n';
// ---------- 可选:重建单源到某个 t 的路径前提t 不受负环影响且可达) ----------
// 示例:如果输入了一个 t则输出路径
int t;
if (cin >> t) {
if (in_neg[t]) {
cout << "Target node " << t << " is affected by a negative cycle; path undefined.\n";
} else if (dist[t] == INF) {
cout << "No path from " << s << " to " << t << '\n';
} else {
vector<int> path;
for (int cur = t; cur != -1; cur = prev[cur]) {
path.push_back(cur);
}
reverse(path.begin(), path.end());
cout << "Path: ";
for (int x : path) cout << x << ' ';
cout << '\n';
}
}
return 0;
}