typedef pair<int, int> pii; constint N = 25010, M = 50010*3, INF = 0x3f3f3f3f; int h[N], e[M], ne[M], w[M], idx; int n, m1, m2, S, dist[N]; int id[N], din[N], bcnt = 1; bool st[N]; vector<int> block[N]; queue<int> q;
voidadd(int a, int b, int c){ e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; }
// Flood-fill booldfs(int u, int bid){ if (id[u]) returnfalse; id[u] = bid; block[bid].push_back(u); for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; if (!id[j]) dfs(j, bid); } returntrue; }
voiddijkstra(int bid){ priority_queue<pii, vector<pii>, greater<pii>> heap; for (int t : block[bid]) { heap.push({dist[t], t}); } while (heap.size()) { pii p = heap.top(); heap.pop(); int t = p.second; if (st[t]) continue; st[t] = true; for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (dist[j] > dist[t] + w[i]) { dist[j] = dist[t] + w[i]; if (id[j] == id[t]) heap.push({dist[j], j}); } if (id[j] != id[t] && -- din[id[j]] == 0) q.push(id[j]); } } }
voidtopsort(){ for (int i = 1; i < bcnt; i++) if (din[i] == 0) q.push(i); memset(dist, 0x3f, sizeof dist); dist[S] = 0; while (q.size()) { int t = q.front(); q.pop(); dijkstra(t); } }
intmain(){ cin >> n >> m1 >> m2 >> S; memset(h, -1, sizeof h); while (m1--) { int a, b, c; cin >> a >> b >> c; add(a, b, c), add(b, a, c); } for (int i = 1; i <= n; i++) if (dfs(i, bcnt)) bcnt++; while (m2--) { int a, b, c; cin >> a >> b >> c; add(a, b, c); din[id[b]]++; } topsort(); for (int i = 1; i <= n; i++) { if (dist[i] > INF / 2) cout << "NO PATH\n"; else cout << dist[i] << '\n'; } return0; }
constint N = 1010, M = 20010; int h[N], e[M], ne[M], w[M], idx; int n, m, k, dist[N]; bool st[N];
voidadd(int a, int b, int c){ e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; }
boolcheck(int x, bool& unreachable){ deque<int> q; q.push_back(1); memset(dist, 0x3f, sizeof dist); memset(st, 0, sizeof st); dist[1] = 0; while (q.size()) { int t = q.front(); q.pop_front(); if (st[t]) continue; st[t] = true; for (int i = h[t]; ~i; i = ne[i]) { int j = e[i], v = w[i] > x; if (dist[j] > dist[t] + v) { dist[j] = dist[t] + v; if (v) q.push_back(j); else q.push_front(j); } } } if (dist[n] == 0x3f3f3f3f) unreachable = true; return dist[n] <= k; }
intmain(){ cin >> n >> m >> k; memset(h, -1, sizeof h); while (m--) { int a, b, c; cin >> a >> b >> c; add(a, b, c), add(b, a, c); } int l = 0, r = 1e6; bool unreachable = false; while (l < r && !unreachable) { int mid = l+r >> 1; if (check(mid, unreachable)) r = mid; else l = mid+1; } if (unreachable) r = -1; cout << r << endl; return0; }
typedef pair<int, int> pii; constint N = 5e4+10, M = 2e5+10; int h[N], e[M], ne[M], w[M], idx, n, m; int dist[6][N], source[6], ans = 2e9; bool st[N];
voidadd(int a, int b, int c){ e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; }
voiddijkstra(int dist[], int S){ memset(dist, 0x3f, sizeof(int) * N); dist[S] = 0; priority_queue<pii, vector<pii>, greater<pii>> heap; heap.push({0, S}); while (heap.size()) { pii p = heap.top(); heap.pop(); int t = p.second; if (st[t]) continue; st[t] = true; for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (dist[j] > dist[t] + w[i]) { dist[j] = dist[t] + w[i]; heap.push({dist[j], j}); } } } memset(st, 0, sizeof st); }
voiddfs(int u, int s, int cnt){ if (cnt >= 5) { ans = min(ans, s); return; } for (int i = 1; i <= 5; i++) { if (!st[i]) { st[i] = true; dfs(i, s+dist[u][source[i]], cnt+1); st[i] = false; } } }
intmain(){ cin >> n >> m; memset(h, -1, sizeof h); source[0] = 1; for (int i = 1; i <= 5; i++) cin >> source[i]; while (m--) { int a, b, c; cin >> a >> b >> c; add(a, b, c), add(b, a, c); } for (int i = 0; i <= 5; i++) dijkstra(dist[i], source[i]); dfs(0, 0, 0); cout << ans << endl; return0; }
拯救大兵瑞恩(状压)
迷宫的外形是一个长方形,其南北方向被划分为 N 行,东西方向被划分为 M 列, 于是整个迷宫被划分为 N×M 个单元。
每一个单元的位置可用一个有序数对 (单元的行号, 单元的列号) 来表示。
南北或东西方向相邻的 2 个单元之间可能互通,也可能有一扇锁着的门,或者是一堵不可逾越的墙。
注意: 门可以从两个方向穿过,即可以看成一条无向边。
迷宫中有一些单元存放着钥匙,同一个单元可能存放 多把钥匙,并且所有的门被分成 P 类,打开同一类的门的钥匙相同,不同类门的钥匙不同。
#define pos first #define stat second #define pp(a, b) a*11+b typedef pair<int, int> pii; constint N = 115, M = 1 << 11; int n, m, p, dist[M][N], g[N][N], key[N]; bool st[M][N]; int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
intdijkstra(){ deque<pii> q; int src = pp(1, 1); q.push_back({src, key[src]}); memset(dist, 0x3f, sizeof dist); dist[key[src]][src] = 0; while (q.size()) { pii t = q.front(); q.pop_front(); if (st[t.stat][t.pos]) continue; st[t.stat][t.pos] = true; int tx = t.pos/11, ty = t.pos%11; if (tx == n && ty == m) return dist[t.stat][t.pos]; // 捡起来当前钥匙 if (key[t.pos] && dist[t.stat|key[t.pos]][t.pos] > dist[t.stat][t.pos]) { dist[t.stat|key[t.pos]][t.pos] = dist[t.stat][t.pos]; q.push_front({t.pos, t.stat | key[t.pos]}); } for (int i = 0; i < 4; i++) { int x = tx+dx[i], y = ty+dy[i], pos = pp(x, y); if (x <= 0 || x > n || y <= 0 || y > m) continue; int wall = g[t.pos][pos]; if (wall == -1) continue; // 没有对应的钥匙 if (wall && !(t.stat >> wall & 1)) continue; if (dist[t.stat][pos] > dist[t.stat][t.pos] + 1) { dist[t.stat][pos] = dist[t.stat][t.pos] + 1; q.push_back({pos, t.stat}); } } } return-1; }
intmain(){ cin >> n >> m >> p; int k; cin >> k; while (k--) { int x1, x2, y1, y2, type; // 读入顺序搞错卡了我半小时 cin >> x1 >> y1 >> x2 >> y2 >> type; // 不可通过的墙设为 -1 if (type == 0) type = -1; g[pp(x1, y1)][pp(x2, y2)] = g[pp(x2, y2)][pp(x1, y1)] = type; } int s; cin >> s; while (s--) { int x, y, z; cin >> x >> y >> z; // 一个格子可能有多个钥匙 key[pp(x, y)] |= 1 << z; } cout << dijkstra() << endl; return0; }
typedeflonglong LL; typedef pair<int, int> PII; constint N = 110010, M = 2200010; int n, m, k, S, T; int h[N], e[M], ne[M], w[M], idx; LL dist[N]; bool st[N];
voidadd(int a, int b, int c){ e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; }
#define int long long #define eb emplace_back constint N = 1000010; typedef pair<int, int> PII; vector<PII> G[N]; int n, m, s[N], rs[N], L[N], R[N], W[N], dis[N]; bool st[N];
voiddijkstra(int S){ for (int i = 1; i <= n*n; i++) dis[i] = 1e18, st[i] = false; priority_queue<PII> heap; heap.push({0, S}); dis[S] = 0; while (heap.size()) { int t = heap.top().second; heap.pop(); if (st[t]) continue; st[t] = true; for (constauto& [w, to]: G[t]) { if (dis[to] > dis[t] + w) { dis[to] = dis[t] + w; heap.push({-dis[to], to}); } } } }
intsolve(){ cin >> n >> m; for (int i = 1; i <= m; i++) cin >> L[i] >> R[i] >> W[i]; for (int i = 1; i <= n; i++) cin >> s[i], rs[s[i]] = i; for (int i = 1; i <= n*n; i++) vector<PII>().swap(G[i]);
for (int i = 1; i <= m; i++) { int a = L[i], b = R[i], w = W[i]; for (int j = 1; j <= n; j++) { int u = (j-1) * n + a, v = (j-1) * n + b; G[u].eb(w*s[j], v); G[v].eb(w*s[j], u); } }
// i: current graph for (int i = 1; i <= n; i++) { // j: current node for (int j = 1; j <= n; j++) { int to = rs[s[j]]; if (to == i) continue; G[(i-1) * n + j].eb(0, (to-1) * n + j); } }
dijkstra(1);
int ans = 1e18; for (int i = 1; i <= n; i++) ans = min(ans, dis[(i-1) * n + n]); return ans; }
signedmain(){ int t; cin >> t; while (t--) cout << solve() << '\n'; return0; }
#define x first #define y second typedef pair<int, int> pii; constint N = 155; constdouble INF = 1e20; int n; char f[N][N]; double g[N][N], d[N]; pii p[N];
doubledist(pii p, pii q){ int dx = p.x-q.x, dy = p.y-q.y; returnsqrt(dx*dx+dy*dy); }
intmain(){ cin >> n; for (int i = 0; i < n; i++) cin >> p[i].x >> p[i].y; for (int i = 0; i < n; i++) cin >> f[i]; // 建图 for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if (i != j) { if (f[i][j] == '1') g[i][j] = dist(p[i], p[j]); else g[i][j] = INF; } // Floyd for (int k = 0; k < n; k++) for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) g[i][j] = min(g[i][j], g[i][k]+g[k][j]); // 直径 double res1 = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) if (g[i][j] < INF) d[i] = max(d[i], g[i][j]); res1 = max(res1, d[i]); } double res2 = INF; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if (g[i][j] >= INF) res2 = min(res2, d[i] + d[j] + dist(p[i], p[j])); return !printf("%.6lf\n", max(res1, res2)); }
voidfloyd(){ for (int k = 0; k < n; k++) for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if (g[i][k] && g[k][j]) g[i][j] = 1; }
// 0: 无法确定 // 1: 已经确定 // 2: 出现矛盾 intcheck(){ for (int i = 0; i < n; i++) if (g[i][i]) return2; // 由对称性可以 j 循环到 i-1 为止 for (int i = 0; i < n; i++) for (int j = 0; j < i; j++) if (g[i][j] == 0 && g[j][i] == 0) return0; return1; }
chargetmin(){ for (int i = 0; i < n; i++) { if (st[i]) continue; bool has_lower = false; for (int j = 0; j < n; j++) if (!st[j] && g[j][i]) has_lower = true; if (has_lower) continue; st[i] = true; return i+'A'; } // unreachable code return'N'; }
intmain(){ while (cin >> n >> m, n || m) { int t = 0, type = 0; memset(g, 0, sizeof g); memset(st, 0, sizeof st); for (int i = 1; i <= m; i++) { char a, _, b; cin >> a >> _ >> b; // 不要遇到别的 type 直接 break 这会导致接下来的读入问题 if (type == 0) { // 这真的很容易写成 a-'A', b-'B', 巨坑 g[a-'A'][b-'A'] = 1; floyd(); type = check(); t = i; } } if (type == 0) puts("Sorted sequence cannot be determined."); elseif (type == 2) printf("Inconsistency found after %d relations.\n", t); else { printf("Sorted sequence determined after %d relations: ", t); for (int i = 0; i < n; i++) printf("%c", getmin()); puts("."); } } return0; }
constint N = 110; int n, m; int g[N][N], d[N][N], pos[N][N]; vector<int> sln;
voidget_mid(int i, int j){ // 没有中间的点 if (pos[i][j] == 0) return; int k = pos[i][j]; get_mid(i, k); sln.push_back(k); get_mid(k, j); }
intmain(){ cin >> n >> m; memset(g, 0x3f, sizeof g); for (int i = 1; i <= n; i++) { g[i][i] = 0; } for (int i = 1; i <= m; i++) { int a, b, c; cin >> a >> b >> c; g[a][b] = g[b][a] = min(g[a][b], c); } memcpy(d, g, sizeof d); int res = 0x3f3f3f3f; for (int k = 1; k <= n; k++) { for (int i = 1; i < k; i++) for (int j = 1; j < i; j++) // 三个 0x3f3f3f3f 可能爆 int if ((longlong)d[i][j] + g[i][k] + g[k][j] < res) { res = d[i][j] + g[i][k] + g[k][j]; sln.clear(); sln.push_back(k); sln.push_back(i); get_mid(i, j); sln.push_back(j); } for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) if (d[i][j] > d[i][k] + d[k][j]) { d[i][j] = d[i][k] + d[k][j]; // i -> k -> j pos[i][j] = k; } } if (sln.size()) for (int s : sln) cout << s << ' '; else cout << "No solution."; return0; }