Mobile Phone Network CodeForces - 1023F (最小生成树)
大意: 无向图, 其中k条边是你的, 边权待定, m条边是你对手的, 边权已知. 求如何设置边权能使最小生成树中, 你的边全被选到, 且你的边的边权和最大. 若有多棵最小生成树优先取你的边.
先将kk条边合并, 然后按边权从小到大添对手的边, 若连通, 则树链取最小值, 否则合并一下.
正确性其实很显然.
然后对于树链取最小有多种方法, 强制在线可以树剖O(nlog2n)O(nlog2n), 可以离线的话可以用倍增O(nlogn)O(nlogn), 或者并查集O(n)O(n).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | #include <iostream> #include <iostream> #include <algorithm> #include <cstdio> #include <math.h> #include <set> #include <map> #include <queue> #include <string> #include <string.h> #include <bitset> #define REP(i,a,n) for(int i=a;i<=n;++i) #define PER(i,a,n) for(int i=n;i>=a;--i) #define hr putchar(10) #define pb push_back #define lc (o<<1) #define rc (lc|1) #define mid ((l+r)>>1) #define ls lc,l,mid #define rs rc,mid+1,r #define x first #define y second #define io std::ios::sync_with_stdio(false) #define endl '\n' #define DB(a) ({REP(__i,1,n) cout<<a[__i]<<' ';hr;}) using namespace std; typedef long long ll; const int N = 1e6+10; int n, k, m, cnt, fa[N]; struct _ { int to,id;} pre[N]; vector<_> g[N]; struct { int u,v,w;} e[N]; int Find( int x) { return fa[x]?fa[x]=Find(fa[x]):x;} int dep[N], ans[N]; void dfs( int x, int d, int f) { dep[x] = d; for (_ e:g[x]) if (e.to!=f) { pre[e.to] = {x,e.id}; dfs(e.to,d+1,x); } } int main() { scanf ( "%d%d%d" , &n, &k, &m); int tot = 0; while (k--) { int u, v; scanf ( "%d%d" , &u, &v); fa[Find(u)] = Find(v); g[u].pb({v,1}),g[v].pb({u,1}); } REP(i,1,m) { int u, v, w; scanf ( "%d%d%d" , &u, &v, &w); int uu = Find(u), vv = Find(v); if (uu==vv) e[++cnt]={u,v,w}; else { fa[uu] = vv; g[u].pb({v,0}), g[v].pb({u,0}); } } dfs(1,0,0); memset (fa,0, sizeof fa); REP(i,1,cnt) { int u = e[i].u, v = e[i].v, w = e[i].w; while (Find(u)!=Find(v)) { if (dep[u]<dep[v]) swap(u,v); if (Find(u)!=Find(pre[u].to)) { fa[u] = Find(pre[u].to); ans[u] = w; } u = Find(u); } } ll sum = 0; REP(i,1,n) if (pre[i].to&&pre[i].id) { if (!ans[i]) return puts ( "-1" ),0; else sum += ans[i]; } printf ( "%lld\n" , sum); } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· .NET 进程 stackoverflow异常后,还可以接收 TCP 连接请求吗?
· 本地部署 DeepSeek:小白也能轻松搞定!
· 基于DeepSeek R1 满血版大模型的个人知识库,回答都源自对你专属文件的深度学习。
· 在缓慢中沉淀,在挑战中重生!2024个人总结!
· 大人,时代变了! 赶快把自有业务的本地AI“模型”训练起来!
· Tinyfox 简易教程-1:Hello World!