for (int t = 0; t < n; t++) { // 循环n轮次 int u = 0; for (int i = 0; i < n; i++) { if (!vis[i] && dis[i] < dis[u]) u = i; } // 从未确定最短路的点中 选取最短路长度最小的点 vis[u] = 1; // 这个点的最短路已经确定 for (int v = 0; v < n; v++) { if (!vis[v]) dis[v] = min(dis[v], dis[u] + E[u][v]); } // 为未确定最短路的点 松弛出边 } return dis; };
auto Floyd = [&]() { auto dis = E; for (int u = 0; u < n; u++) dis[u][u] = 0; for (int k = 0; k < n; k++) { for (int u = 0; u < n; u++) { for (int v = 0; v < n; v++) dis[u][v] = min(dis[u][v], dis[u][k] + dis[k][v]); if (dis[u][u] < 0) return vector<vector<ll>>(); // 存在负环 } } return dis; // 没有负环 }
vector<pair<int, int>> train; vector<vector<pair<int, int>>> E(n); // 邻接表存边 while (m--) { int u, v, w; cin >> u >> v >> w; u--, v--; E[u].push_back({ w, v }); E[v].push_back({ w, u }); }
while (k--) { int v, w; cin >> v >> w; v--; E[0].push_back({ w, v }); E[v].push_back({ w, 0 }); train.push_back({ w, v }); }
int n, m; cin >> n >> m; vector<vector<pair<int, int>>> E(n); vector<array<int, 3>> edge(m); for (int i = 0; i < m; i++) { int u, v, w; cin >> u >> v >> w; u--, v--; E[u].push_back({ w, v }); E[v].push_back({ w, u }); edge[i] = { u, v, w }; }
auto Dijkstra = [&](int s) { vector dis(n, Inf); vector<int> vis(n); vector<int> from(n, -1); vector<ll> pcnt(n); dis[s] = 0, pcnt[s] = 1; priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> Q; Q.push({ 0, s }); while (!Q.empty()) { auto [d, u] = Q.top(); Q.pop(); if (vis[u]) continue; vis[u] = 1; for (auto& [w, v] : E[u]) { if (dis[v] > w + d) { dis[v] = w + d; from[v] = u; pcnt[v] = pcnt[u]; Q.push({ dis[v], v }); } elseif (dis[v] == w + d) { (pcnt[v] += pcnt[u]) %= mod; } } } returnmake_pair(dis, pcnt); }; auto [d1, p1] = Dijkstra(0); auto [dn, pn] = Dijkstra(n - 1);
for (auto& [u, v, w] : edge) { if (d1[u] > d1[v]) swap(u, v); bool only = (d1[u] + w + dn[v] == dn[0]) && (p1[u] * pn[v] % mod == pn[0]); cout << (only ? "Yes" : "No") << "\n"; }
int N = n * k; vector<vector<pii>> E(N); auto add = [&](int f, int t, int u, int v, int w) { E[f * n + u].push_back({ w, t * n + v }); E[f * n + v].push_back({ w, t * n + u }); };
voideachT(){ int n, m, k, st, ed; cin >> n >> m >> k >> st >> ed; ++k;
int N = n * k; vector<vector<pii>> E(N); auto add = [&](int f, int t, int u, int v, int w) { E[f * n + u].push_back({ w, t * n + v }); E[f * n + v].push_back({ w, t * n + u }); }; while (m--) { int u, v, w; cin >> u >> v >> w; for (int i = 0; i < k; i++) add(i, i, u, v, w); for (int i = 1; i < k; i++) add(i - 1, i, u, v, 0); }
auto dis = Dijkstra(st); int ans = inf; for (int i = 0; i < k; i++) { ans = min(ans, dis[i * n + ed]); } cout << (ans == Inf ? -1 : ans) << '\n'; }
int N = n * 4; vector<vector<pii>> E(N); auto add = [&](int f, int t, int u, int v, int w) { E[f * n + u].push_back({ w, t * n + v }); E[f * n + v].push_back({ w, t * n + u }); }; while (m--) { int u, v, w; cin >> u >> v >> w; u--, v--; for (int i = 0; i < 4; i++) add(i, i, u, v, w); add(0, 1, v, u, 0); add(1, 3, v, u, 2 * w); add(0, 2, v, u, 2 * w); add(2, 3, v, u, 0); }
auto dis = Dijkstra(0); for (int i = 1; i < n; i++) { cout << min(dis[i], dis[3 * n + i]) << ' '; } }
vector<vector<int>> E(n); while (m--) { int u, v; cin >> u >> v; u--, v--; E[u].push_back(v); E[v].push_back(u); }
queue<pair<int, int>> Q;
vector val(n, array{ inf, inf }); int k; cin >> k; while (k--) { int x; cin >> x; x--; val[x][0] = 0; Q.push({ 0, x }); }
while (!Q.empty()) { auto [d, u] = Q.front(); Q.pop(); if (d >= D) continue; ++d; for (auto& v : E[u]) { if (val[v][d & 1] != inf) continue; val[v][d & 1] = d; Q.push({ d, v }); } }
vector from(n, array{ -1, -1 }); Q.push({ 0, 0 }); while (!Q.empty()) { auto [d, u] = Q.front(); Q.pop();
if (u == n - 1) { cout << d << '\n'; vector<int> path; while (d >= 0) { path.push_back(u); u = from[u][d & 1]; d--; } for (int i = path.size() - 1; i >= 0; --i) { cout << path[i] + 1 << ' '; } cout << '\n'; return0; }
++d; for (auto& v : E[u]) { if (d >= val[v][d & 1]) continue; if (~from[v][d & 1]) continue; from[v][d & 1] = u; Q.push({ d, v }); } }
cout << "-1\n";
例 5 Alice 和 Bob 在一张简单无向图上博弈,Alice 先手。每次每人必须沿着当前所在的点的一条边走到另一端,不能走到对手所在的位置,不能行动者输。对于每个i 从1 到n−1,求出 Alice 初始在0 号点,Bob 初始在i 号点,谁会赢或平局。(SunBoYi [[…/contests/2024杭电多校/2024-08-18:2024“钉耙编程”中国大学生算法设计超级联赛(10)|2024-08-18:2024“钉耙编程”中国大学生算法设计超级联赛(10)]])
vector f(D, vector(n, vector<int>(n))); while (m--) { int u, v; cin >> u >> v; u--, v--; f[0][u][v] = 1; }
// 倍增 for (int bit = 1; bit < D; bit++) { for (int k = 0; k < n; ++k) for (int u = 0; u < n; u++) for (int v = 0; v < n; v++) f[bit][u][v] |= f[bit - 1][u][k] & f[bit - 1][k][v]; }
// 建图 vector adj(n, vector(n, inf)); for (int u = 0; u < n; u++) { for (int v = 0; v < n; v++) for (int bit = 0; bit < D; bit++) if (f[bit][u][v]) adj[u][v] = 1; }
// Floyd for (int k = 0; k < n; ++k) { for (int u = 0; u < n; u++) for (int v = 0; v < n; v++) adj[u][v] = min(adj[u][v], adj[u][k] + adj[k][v]); }
int n, m; cin >> n >> m; vector<vector<pair<int, int>>> E(n); while (m--) { int u, v, w; cin >> u >> v >> w; u--, v--; E[u].push_back({ w, v }); E[v].push_back({ w, u }); }
auto dis = Dijkstra(0);
if (dis[n - 1] == Inf) { cout << "inf\n"; } else { vector<int> pos(n); iota(pos.begin(), pos.end(), 0); sort(pos.begin(), pos.end(), [&](constint& a, constint& b) { return dis[a] == dis[b] ? a < b : dis[a] < dis[b]; // WA: 相等的时候有没有影响 });
vector<pair<string, ll>> res; string s(n, '0'); for (int i = 0; i < n; i++) { if (pos[i] == n - 1) break; // WA s[pos[i]] = '1'; res.push_back({ s, dis[pos[i + 1]] - dis[pos[i]] }); }
int n, m, q; cin >> n >> m >> q; vector<array<int, 3>> E(m); for (int i = 0; i < m; i++) { int u, v, w; cin >> u >> v >> w; u--, v--; E[i] = { u, v, w }; }
vector<array<int, 3>> que(q); vector<int> del(m); for (int i = 0; i < q; i++) { int op; cin >> op; if (op == 1) { int x; cin >> x; x--; del[x] = 1; que[i] = { op, x, 0 }; } else { int u, v; cin >> u >> v; u--, v--; que[i] = { op, u, v }; } }
vector dis(n, vector(n, Inf)); for (int u = 0; u < n; u++) { dis[u][u] = 0; } for (int i = 0; i < m; i++) { if (!del[i]) { auto [u, v, w] = E[i]; dis[u][v] = dis[v][u] = w; } } for (int k = 0; k < n; ++k) { for (int u = 0; u < n; u++) { for (int v = 0; v < n; v++) { dis[u][v] = min(dis[u][v], dis[u][k] + dis[k][v]); } } }
vector<ll> ans(q); for (int i = q - 1; i >= 0; i--) { auto [op, a, b] = que[i]; if (op == 1) { auto [s, t, w] = E[a]; for (int u = 0; u < n; u++) { for (int v = 0; v < n; v++) dis[u][v] = min(dis[u][v], min(dis[u][s] + dis[t][v] + w, dis[u][t] + dis[s][v] + w)); } } else { ans[i] = dis[a][b]; } }
for (int i = 0; i < q; i++) { if (ans[i]) cout << (ans[i] == Inf ? -1 : ans[i]) << "\n"; }
vector<int> c(n), w(n); for (int i = 0; i < n; i++) { cin >> c[i]; } for (int i = 0; i < n; i++) { cin >> w[i]; }
vector adj(n, vector<int>(n)); vector dis(n, vector<ll>(n, Inf)); while (m--) { int u, v; cin >> u >> v; u--, v--; adj[u][v] = adj[v][u] = 1; if (c[u] == c[v]) { dis[u][v] = dis[v][u] = w[u] + w[v]; } } for (int u = 0; u < n; u++) { dis[u][u] = w[u]; }
// 点权Floyd u,v,k的颜色相同 for (int k = 0; k < n; ++k) { for (int u = 0; u < n; u++) { if (c[u] != c[k]) continue; for (int v = 0; v < n; v++) { if (c[v] != c[u]) continue; dis[u][v] = min(dis[u][v], dis[u][k] + dis[k][v] - w[k]); dis[v][u] = min(dis[v][u], dis[v][k] + dis[k][u] - w[k]); } } }
// 点权Dijkstra u,v在一个团 s是另一个团的起点 for (int u = 0; u < n; u++) { for (int v = 0; v < n; v++) { if (c[u] != c[v]) continue; for (int s = 0; s < n; ++s) { if (c[v] != c[s] && adj[v][s]) dis[u][s] = min(dis[u][s], dis[u][v] + w[s]); } } }
for (int s = 0; s < n; ++s) { // Prim 有向最小瓶颈路 vector<ll> mn(n, Inf), dp(n, Inf), ndp(n, Inf); vector<int> vis(n); dp[s] = mn[s] = 0; for (int t = 0; t < n; t++) { int u = -1; for (int j = 0; j < n; j++) { if (!vis[j] && (u == -1 || mn[j] < mn[u])) { u = j; } } if (u == -1) break; vis[u] = 1; for (int v = 0; v < n; v++) { if (!vis[v] && c[u] != c[v] && dis[u][v] < mn[v]) { mn[v] = dis[u][v]; dp[v] = max(dp[u], mn[v]); // 顺带做树形dp 求有向最小瓶颈路 } } }
// 再做一次点权Dijkstra for (int u = 0; u < n; u++) { for (int v = 0; v < n; v++) { if (c[u] == c[v]) ndp[v] = min(ndp[v], max(dp[u], dis[u][v])); } } for (int u = 0; u < n; u++) { dp[u] = min(dp[u], ndp[u]); }
// 输出 for (int u = 0; u < n; u++) { cout << dp[u] << " \n"[u == n - 1]; } } } return0; }