CF76A gift
题目简述:
给定一个有
Solution:
最小生成树好题。
通过题面容易联想到最小生成树,与普通的最小生成树有区别的是,这道题是有两个限制的。
首先考虑消掉一个限制,即枚举
此时可以直接做一遍
但是时间复杂度是
建图可以通过维护指针优化到均摊
进而有一个比较好猜的结论:
- 对于一条之前不是最小生成树上的边,即使加入一些边之后,它依旧不是最小生成树上的边。
证明如下:
考虑加入一条边
对于刚加入的某一条边
加入某一条边之后,假如它替换掉了某一条边,那么通过上面的公式,显然不会使得最大值更大。
所以条件不变,不是最小生成树上的边依旧没用。
所以我们只维护原来在最小生成树的边,边的规模由
时间复杂度降为
code:
#include<bits/stdc++.h> #define int long long using namespace std; const int N = 200 + 10, M = 5e4 + 10 , INF = 9000000000000000000; struct Edge{ int from, to; int g, s; }E[M], E2[M]; int n, m, costs, costg, Ecnt; bool cmpE(struct Edge E1, struct Edge E2){return E1.g < E2.g;} int fda[N]; int getfa(int x){return fda[x] = (fda[x] == x)? x : getfa(fda[x]);} signed main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m >> costg >> costs; int ans = INF; for(int i = 1; i <= m; i++)cin >> E[i].from >> E[i].to >> E[i].g >> E[i].s; sort(E + 1, E + m + 1, cmpE); for(int i = 1; i <= m; i++){ int pos = ++Ecnt; while(pos > 1 &&E2[pos - 1].s > E[i].s){ E2[pos] = E2[pos - 1]; pos--; } E2[pos] = E[i]; for(int j = 1; j <= n; j++)fda[j] = j; int newcnt = 0, cnts = 0, cntg = 0; for(int j = 1; j <= Ecnt; j++){ if(getfa(E2[j].from) == getfa(E2[j].to))continue; fda[getfa(E2[j].from)] = getfa(E2[j].to); E2[++newcnt] = E2[j]; cnts = max(cnts, E2[j].s); cntg = max(cntg, E2[j].g); } Ecnt = newcnt; if(Ecnt >= n - 1)ans = min(ans, cnts * costs + cntg * costg); } if(ans != INF)cout << ans; else cout << -1; return 0; }
换了一个更好看的码风 qwq
本文作者:Little_corn
本文链接:https://www.cnblogs.com/little-corn/p/18157499
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
标签:
,
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步