abc270_f Transportation 题解
1.CSES 1667 Message Route 题解2.P3956 棋盘 题解3.abc233_f Swap and Sort 题解4.abc233_e Σ[k=0..10^100]floor(X/10^k) 题解5.abc233_d Interval 题解6.abc233_c Product 题解7.abc249_f Ignore Operations 题解8.abc249_d Index Trio 题解9.abc248_e K-colinear Line 题解10.abc247_f Cards 题解11.CF1066C Books Queries 题解12.P1038 神经网络 题解13.SeekLuna P1362 拓扑排序 3 题解14.abc232_e Rook Path 题解15.abc235_e MST + 1 题解16.abc234_e Arithmetic Number 题解17.P8786 李白打酒加强版 题解18.abc235_d Multiply and Rotate 题解19.CF1095D Circular Dance 题解20.P6201 & P1985 Fliptile S 题解21.CF1183C Computer Game 题解22.CF1095E Almost Regular Bracket Sequence 题解23.abc256_e Takahashi's Anguish 题解24.abc260_g Scalene Triangle Area 题解25.P8714 填空问题 题解26.abc252_d Distinct Trio 题解27.abc252_f Bread 题解28.abc253_e Distance Sequence 题解29.abc250_e Prefix Equality 题解30.abc250_d 250-like Number 题解31.arc164_a Ternary Decomposition 题解32.abc275_f Erase Subarrays 题解33.abc275_e Sugoroku 4 题解34.abc274_d Robot Arms 2 题解35.abc260_f Find 4-cycle 题解36.abc260_e At Least One 题解37.abc273_e Notebook 题解38.abc271_f XOR on Grid Path 题解39.abc271_e Subsequence Path 题解40.abc271_c Manga 题解41.abc269_f Numbered Checker 题解
42.abc270_f Transportation 题解
43.CF1077E Thematic Contests 题解44.CF1935D Exam in MAC 题解45.CF1144G Two Merged Sequences 题解46.joi2022_yo2_c 国土分割 (Land Division) 题解47.P3588 PUS 题解48.CF1946F Nobody is needed 题解Transportation
题意
有
- 选择一个没有建机场的城市
,花费 建一个机场。 - 选择一个没有建港口的城市
,花费 建一个港口。
还有
两个城市
和 都有机场。 和 都有港口。 和 直接有一条道路。
求最小花费,使得从任意一个城市
思路
这题只考建图和最小生成树。
初步考虑
首先,不看机场和港口,那么就变成了一个最小生成树问题。
特殊情况
那么有机场呢?画张草图看看吧。
上面那种建图方式,就是在两个有机场的城市间建边,不仅难以维护花费,你也不知道有多少个城市建了机场,建图方式不够优秀。
优化建图
这种建图方式值得思考。
根据题意,两个有机场的城市可以互相抵达,相当于有一个机场聚集地,设立机场的城市可以来到这个聚集地,并从这里走向另外一个设立机场的城市。
那么维护起来就很方便了,假定机场聚集地在
上图就会变成:
港口同理,将聚集地设置为与机场聚集地不同的一个即可(也不能和任何一座城市下标相同),建议设为
最后思考
可我并不知道是否要通过建立机场或港口来互相抵达啊?
这个也不难,枚举是否建立机场和是否建立港口,每次跑一遍克鲁斯卡尔,求出
复杂度
- 时间:
。 - 空间:
。
Code
点击查看代码
#include <iostream> #include <algorithm> using namespace std; using ll = long long; const int N = 2e5 + 10, E = 6e5 + 10; struct Edge { int x, y, z; bool operator < (const Edge &i) const { return z < i.z; } } e[N], a[E]; int n, m, x[N], y[N], fa[N], ae; ll ans = 1e18; int Find (int x) { return (fa[x] ? fa[x] = Find(fa[x]) : x); } ll kruskal (bool f1, bool f2) { // 克鲁斯卡尔算法 ll sum = 0; int num = 0; sort(a + 1, a + ae + 1); for (int i = 1; i <= ae; i++) { // 这些不用说了吧 int l = Find(a[i].x), r = Find(a[i].y); if (l != r) { sum += a[i].z, num++, fa[l] = r; } } if (num == n + f1 + f2 - 1) { // 注意!题目并不保证在只走普通道路的情况下一定合法,需判断 return sum; } return 1e18; } int main () { ios::sync_with_stdio(0), cin.tie(0); cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> x[i]; } for (int i = 1; i <= n; i++) { cin >> y[i]; } for (int i = 1; i <= m; i++) { cin >> e[i].x >> e[i].y >> e[i].z; } for (int i = 0; i < 2; i++) { // 是否建立机场 for (int j = 0; j < 2; j++) { // 是否建立港口 for (int k = 1; k <= n + 2; k++) { fa[k] = 0; // 先清空 } ae = 0; for (int k = 1; k <= m; k++) { // m 条道路 a[++ae] = e[k]; } if (i) { // 走机场 for (int k = 1; k <= n; k++) { a[++ae] = {k, n + 1, x[k]}; } } if (j) { // 走港口 for (int k = 1; k <= n; k++) { a[++ae] = {k, n + 2, y[k]}; } } ans = min(ans, kruskal(i, j)); } } cout << ans; return 0; }
本文作者:wnsyou の blog
本文链接:https://www.cnblogs.com/wnsyou-blog/p/17410723.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步