CF125E MST Company 题解
代码写的可能比较繁琐,请见谅。
思路#
首先考虑
对所有连向
即所有连向
就可以将这一个问题变成一个可行性问题。
可能比较困难的一点就是当
本篇主要讲述如何构造一个正确的方案。
首先判断一个无解的情况。
- 从
的出边不足 。 - 原图不联通。
- 使原图联通
必须连的出边超过 。
除去上面三种情况,所有的情况必然会有一个解。
考虑对于一个偏移量如何构造出这样的一个解。
首先可以构造出一组
考虑在此基础上将其增加至
对于相同权值的边,我们先将原方案中所连的出边进行连接。
然后如果不足
最后再去考虑相同权值下的其他边。
可以发现,原方案中所连的出边一定还会在新方案中被连。
这是由于虽然我们增加了一些边,但对于原方案中所连的出边所更改的联通性是不会进行改变的(不然就会出现在原方案中)。
容易发现这样也一定不会比原方案更劣(原理大致与朴素的
这样就有了一个大致的算法流程。
具体可以看代码。
Code#
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1000010;
int n, m, k, s, kl, top, fa[N], vis[N], ans[N];
class Graph
{
public:
int cnt;
struct edge { int to, nxt, val, id; }e[N];
inline edge &operator[](int tmp) { return e[tmp]; }
inline void init(int x) { for (int i = 1;i <= cnt;i++) e[i].val += x; }
inline void add(int x , int y , int z , int i) { e[++cnt] = {x, y, z, i}; }
inline void mySort() { sort(e + 1, e + cnt + 1, [](edge a, edge b) { return a.val < b.val; }); }
} graBlack, graWhite;
inline int read()
{
int asd = 0 , qwe = 1; char zxc;
while(!isdigit(zxc = getchar())) if(zxc == '-') qwe = -1;
while(isdigit(zxc)) asd = asd * 10 + zxc - '0' , zxc = getchar();
return asd * qwe;
}
inline bool check(int x , int y) { return (x == s || y == s); }
inline int gf(int x) { return (fa[x] == x ? fa[x] : fa[x] = gf(fa[x])); }
inline bool merge(int x , int y)
{
int fx = gf(x), fy = gf(y);
if(fx == fy) return 0;
fa[fx] = fy; return 1;
}
inline int kruskal()
{
int num = 0; top = 0;
iota(fa + 1, fa + n + 1, 1);
for (int i = 1, l = 1, r = 1; i <= m; i++)
if (l <= graBlack.cnt && graBlack[l].val < graWhite[r].val)
merge(graBlack[l].to, graBlack[l].nxt) , l++;
else num += merge(graWhite[r].to, graWhite[r].nxt), r++;
return num;
}
inline void checkSol()
{
int cnt = 0 , sum = 0;
for (int i = 1; i <= graBlack.cnt;i++)
cnt += merge(graBlack[i].to, graBlack[i].nxt);
for (int i = 1; i <= graWhite.cnt; i++)
if(merge(graWhite[i].to, graWhite[i].nxt)) cnt++, sum++;
if (cnt != n - 1 || sum > k || graWhite.cnt < k)
puts("-1"), exit(0);
}
inline void makeSol(int mid)
{
graWhite.init(mid), top = 0;
iota(fa + 1, fa + n + 1, 1);
int sum = 0, l = 1, r = 1, i, j;
for (i = 1; i <= m; i++)
if (l <= graBlack.cnt && graBlack[l].val <= graWhite[r].val)
merge(graBlack[l].to, graBlack[l].nxt), l++;
else
{
if (merge(graWhite[r].to, graWhite[r].nxt))
vis[r] = 1, k--;
r++;
};
l--, r--, top = 0;
iota(fa + 1, fa + n + 1, 1);
for (i = 1, j = 1; i <= graBlack.cnt;i++)
{
while(j <= r && graWhite[j].val <= graBlack[i].val)
{
int ls = j, rs = j;
int x = graWhite[j].val;
while(rs < r && graWhite[rs + 1].val == x)
rs++;
for (int j = ls; j <= rs;j++)
if (vis[j] && merge(graWhite[j].to, graWhite[j].nxt))
sum += graWhite[j].val, ans[++top] = graWhite[j].id;
for (int j = ls; j <= rs && k; j++)
if(merge(graWhite[j].to, graWhite[j].nxt))
sum += graWhite[j].val, k--, ans[++top] = graWhite[j].id;
j = rs + 1;
}
if(merge(graBlack[i].to, graBlack[i].nxt))
sum += graBlack[i].val, ans[++top] = graBlack[i].id;
}
while (j <= r)
{
int ls = j, rs = j;
int x = graWhite[j].val;
while (rs < r && graWhite[rs + 1].val == x)
rs++;
for (int j = ls; j <= rs; j++)
if (vis[j] && merge(graWhite[j].to, graWhite[j].nxt))
sum += graWhite[j].val, ans[++top] = graWhite[j].id;
for (int j = ls; j <= rs && k; j++)
if (merge(graWhite[j].to, graWhite[j].nxt))
sum += graWhite[j].val, k--, ans[++top] = graWhite[j].id;
j = rs + 1;
}
cout << n - 1 << endl;
for (i = 1; i <= top;i++)
cout << ans[i] << " ";
cout << endl;
}
inline void wqsDichotomous()
{
int l = -1e9, r = 1e9;
graBlack.mySort(), graWhite.mySort();
while (l <= r)
{
int mid = (l + r) >> 1;
graWhite.init(mid);
int x = kruskal();
graWhite.init(-mid);
if (x > k) l = mid + 1;
if (x < k) r = mid - 1;
if (x == k) break;
}
makeSol((l + r) >> 1);
}
signed main()
{
n = read(), m = read(), s = 1, kl = k = read();
iota(fa + 1, fa + n + 1, 1);
for (int i = 1; i <= m; i++)
{
int x = read(), y = read(), z = read();
if (check(x, y)) graWhite.add(x, y, z, i);
else graBlack.add(x, y, z, i);
}
checkSol(), wqsDichotomous();
return 0;
}
作者:JiaY19
出处:https://www.cnblogs.com/JiaY19/p/16852540.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)