CF1149D Abandoning Roads 题解
Description
一张
Solution
先考虑一个最小生成树是什么样的形态,显然保留边权为
所以树上两点的简单路径一定是先走
这样就可以 dp 了,设
时间复杂度:
考虑优化。
注意到对于一个大小不超过
时间复杂度:
Code
#include <bits/stdc++.h> #define int int64_t const int kMaxN = 75, kMaxS = (1 << 18); int n, m, a, b, cnt, tot; int g[kMaxN][kMaxN], id[kMaxN], f[kMaxN][kMaxS]; bool vis[kMaxN]; std::vector<int> vec; void dfs(int u) { vec.emplace_back(u), vis[u] = 1; for (int i = 1; i <= n; ++i) if (g[u][i] == a && !vis[i]) dfs(i); } void dijkstra() { static bool vis[kMaxN][kMaxS] = {0}; memset(f, 0x3f, sizeof(f)); std::priority_queue<std::tuple<int, int, int>> q; f[1][0] = 0, q.emplace(0, 1, 0); for (; !q.empty();) { auto [d, i, s] = q.top(); q.pop(); if (vis[i][s]) continue; vis[i][s] = 1; for (int j = 1; j <= n; ++j) { if (!g[i][j]) continue; int t = s; if (id[j] < cnt) { if (s >> id[j] & 1) continue; if (id[j] == id[i]) { if (g[i][j] == a && f[j][t] > f[i][s] + g[i][j]) { f[j][t] = f[i][s] + g[i][j], q.emplace(-f[j][t], j, t); } } else { if (id[i] < cnt) t |= (1 << id[i]); if (f[j][t] > f[i][s] + g[i][j]) { f[j][t] = f[i][s] + g[i][j], q.emplace(-f[j][t], j, t); } } } else { if (id[j] == id[i]) { if (g[i][j] == a && f[j][t] > f[i][s] + g[i][j]) { f[j][t] = f[i][s] + g[i][j], q.emplace(-f[j][t], j, t); } } else { if (id[i] < cnt) t |= (1 << id[i]); if (f[j][t] > f[i][s] + g[i][j]) { f[j][t] = f[i][s] + g[i][j], q.emplace(-f[j][t], j, t); } } } } } } void dickdreamer() { std::cin >> n >> m >> a >> b; for (int i = 1; i <= m; ++i) { int u, v, w; std::cin >> u >> v >> w; g[u][v] = g[v][u] = w; } for (int i = 1; i <= n; ++i) { if (vis[i]) continue; dfs(i); if (vec.size() >= 4) { for (auto x : vec) id[x] = tot; ++cnt, ++tot; } vec.clear(); } std::fill_n(vis + 1, n, 0); for (int i = 1; i <= n; ++i) { if (vis[i]) continue; dfs(i); if (vec.size() <= 3) { for (auto x : vec) id[x] = tot; ++tot; } vec.clear(); } dijkstra(); for (int i = 1; i <= n; ++i) std::cout << *std::min_element(f[i], f[i] + (1 << cnt)) << ' '; } int32_t main() { #ifdef ORZXKR freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0); int T = 1; // std::cin >> T; while (T--) dickdreamer(); // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n"; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步