【MST】【并查集】【贪心】Graph practice T4 airplane 题解
来源:互联网 发布:淘宝 假货 投诉 编辑:程序博客网 时间:2024/05/17 07:10
Problem 4. airplane
Input file: airplane.in
Output file: airplane.out
Time limit: 1 second
cky 公司的运营蒸蒸日上,由于出差实在太频繁,而且坐汽车有些太慢了,所以cky 想要顺势直接进驻航空
业。cky 所在的国家天朝有n 个城市,m 个航空公司,每两个城市之间可能有一条航线运营(双向),一共
有k 条航线,每条航线都属于某一航空公司。现在cky 希望收购一家航空公司(为了涉足航空业以及防垄断,
cky 必须且只能购买一家航空公司),使得他能通过飞机从任意城市到达目的城市(允许转机),当然很可能没
有一家公司能满足cky 的要求,所以cky 还需收购其他公司掌控的航线。每个航空公司都有一个市值,每条
航线都有一个收购价。现在cky 想知道他最少需要花费多少钱。
Input
第1 行,3 个整数n; m; k,表示城市数量,航空公司数和航线数。城市用1; 2; : : : ; n 编号。
接下来一行,一共m 个整数,第i 个整数ai 表示第i 个航空公司的市值。接下来k 行,每行4 个整数
ui; vi; costi; bi,表示第i 条航线连接城市u; v,价值costi,所属航空公司为bi
题目保证u! = v
题目保证有解。
Output
输出最少需要花费多少钱
Sample
airplane.in airplane.out
4 3 3
100 150 200
1 2 100 1
1 3 160 2
1 4 220 3
460
Note
• 对于50% 的数据,1 n 1000,1 m 1000,1 k 10000;
• 对于100% 的数据,1 n 2000,1 m 2000,1 k 200000,1 bi m,1 costi; ai 108。
Airplane:最小生成树
最朴素的做法:枚举航空公司,将本公司的航线加入,然后做一遍MST,时间复杂度是O(klogk+mk)的。
但我们注意到“在最小生成树中任意一条边都是连接两个集合边权最小的一条边”,这个是MST一个非常重要的结论,是Prim和kruscal算法中贪心的核心。利用这条性质我们可以知道,对于每个航空公司,我们只需要原图MST中得到的航线即可得到最优购买方案。所以更优的做法是:先跑一次MST,把得到的边记录下来,然后枚举航空公司,还是先讲本公司的边全部加进去,然后只用扫一边第一次MST中记录下来的边,用kruscal的方法去构造树即可。时间复杂度为O(klogk+nm)。
对于本题,50%的数据是可以O(mk)过的,最后30%的数据我特别构造了一下,必须枚举到排序后的最后几条边才能构造出一颗生成树,所以O(mk)应该是过不了的,此外的20%数据是随机数据,加了构造出树就跳出判断的代码可能会过(但是jyb写的mk的没过。。);另外,50%的数据需要long long
#include <cstdio>#include <algorithm>#define ll long longusing namespace std;const int M = 200002;const int N = 2002;const ll INF = 1ll<<60;template <class T> inline void read(T &x) { int flag = 1; x = 0; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') flag = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x<<1)+(x<<3)+ch-'0'; ch = getchar(); } x *= flag;}struct data { int u,v;ll w; bool operator < (const data &rhs) const {return w<rhs.w; }}dis[M],mst[N];struct edges { int u,v,next; } edge[M];int hu[N],num,fa[N],n,m,k,cnt,u,v,tmp,w;ll ans,a[N];inline void addedge(int tmp, int u, int v) { edge[++num].u = u; edge[num].v = v; edge[num].next = hu[tmp]; hu[tmp] = num;}int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }int main() { freopen("airplane.in","r",stdin); freopen("airplane.out","w",stdout); read(n), read(m), read(k); for(register int i = 1; i <= m; i++) read(a[i]); for(register int i = 1; i <= k; i++) { read(dis[i].u), read(dis[i].v), read(dis[i].w), read(tmp); addedge(tmp, dis[i].u, dis[i].v); } sort(dis+1, dis+1+k); for(register int i = 1; i <= n; i++) fa[i] = i; for(register int i = 1; i <= k; i++) { int x = find(dis[i].u), y = find(dis[i].v); if(x != y) fa[y] = x, mst[++cnt]=dis[i]; } ans = INF; for(register int i = 1; i <= m; i++) { for(register int j = 1; j <= n; j++) fa[j] = j; for(register int j = hu[i]; j; j = edge[j].next) { int x = find(edge[j].u), y = find(edge[j].v); if(x != y) fa[y] = x; } ll tot = 0; for(register int j = 1; j <= cnt; j++) { int x = find(mst[j].u), y = find(mst[j].v); if(x != y) fa[y] = x, tot += mst[j].w; } ans = min(ans, tot+a[i]); } printf("%I64d\n",ans); return 0;}
- 【MST】【并查集】【贪心】Graph practice T4 airplane 题解
- 【并查集】Graph practice T1 bricks 题解
- MST&&并查集
- 省选集训 airplane 并查集&&最小生成树
- 并查集&MST题集
- 并查集&MST题集
- 并查集&MST题集
- 并查集&MST题集
- 并查集&MST爬坑中。。。。
- 并查集&MST题集
- 并查集&MST题集
- 并查集题解
- hdu5627 Clarke and MST (并查集)
- 贪心+并查集
- 贪心+并查集
- 【最短路】Graph practice T2 drive 题解
- 并查集系列题解
- 并查集(题解)
- sqlserver数据库实验一
- 工厂设计模式
- cocos学习笔记(四)文本
- 【lightoj】1141
- Spark中函数addFile和addJar函数介绍
- 【MST】【并查集】【贪心】Graph practice T4 airplane 题解
- Trapping Rain Water
- 用XAMPP在本地安装调试WordPress【图文教程】
- 几种常见Dialog,懒人必收
- static关键字
- d3_v4 shape系列之Arc\Pie\Symbol
- Java控制台乘法表
- ubuntu gdb调试第一次实验总结
- String的个人记录