1 条题解
-
0
自动搬运
来自洛谷,原作者为

swiftc
write the code,change the world搬运于
2025-08-24 22:39:47,当前版本为作者最后更新于2023-03-20 22:45:48,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
考虑将所有放长椅的地方黑白染色,黑色的只连横着的边,白色的只连竖着的边,考虑从上到下,从左到右加入所有边,并尽量保证我们当前的图与所有边都加入的图连通性相同,黑色块上面的边和白色块左面的边一定能加入,只需要考虑两种情况:
- 黑色块下面的边

此时三条绿色的边一定已经(可能以等价形式)加入,这条边一定不用加入。
- 白色块右面的边

此时两条绿色的边已经加入,而蓝色的边因为在黑色块上面而一定能加入,于是这条边也不用加入。
所以从实现上来说只需要依次检验所有边是否能加入即可。
// #include "parks.h" #include <algorithm> #include <functional> #include <iostream> #include <map> #include <vector> using namespace std; void build(vector<int> u, vector<int> v, vector<int> a, vector<int> b); int construct_roads(vector<int> x, vector<int> y) { int n = x.size(); vector<int> f(n, 0); for (int i = 0; i < n; i++) f[i] = i; function<int(int)> gf = [&](int x) { return f[x] == x ? x : f[x] = gf(f[x]); }; vector<pair<int, int>> v; map<pair<int, int>, int> mp, used; for (int i = 0; i < n; i++) mp[{x[i], y[i]}] = i, v.push_back({x[i], y[i]}); sort(v.begin(), v.end(), [&](auto a, auto b) { if (a.second != b.second) return a.second > b.second; return a.first < b.first; }); vector<int> vu, vv, va, vb; for (auto [x, y] : v) { if (mp.count({x + 2, y})) { int u = mp[{x, y}], v = mp[{x + 2, y}]; if (gf(u) != gf(v)) { int cx = x + 1, cy = y + 1; if (((cx / 2) + (cy / 2)) & 1) cy -= 2; if (used.count({cx, cy})) continue; used[{cx, cy}] = 1; vu.push_back(u), vv.push_back(v), va.push_back(cx), vb.push_back(cy); f[gf(u)] = gf(v); } } if (mp.count({x, y - 2})) { int u = mp[{x, y}], v = mp[{x, y - 2}]; if (gf(u) != gf(v)) { int cx = x + 1, cy = y - 1; if (!(((cx / 2) + (cy / 2)) & 1)) cx -= 2; if (used.count({cx, cy})) continue; used[{cx, cy}] = 1; vu.push_back(u), vv.push_back(v), va.push_back(cx), vb.push_back(cy); f[gf(u)] = gf(v); } } } bool flag = 1; for (int i = 1; i < n; i++) flag &= (gf(i) == gf(0)); if (!flag) return 0; build(vu, vv, va, vb); return 1; }
- 1
信息
- ID
- 8032
- 时间
- 3000ms
- 内存
- 2048MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者