CF125E MST company (凸优化+MST)
qwq自闭的一个题
我来修锅辣!!!!!!
这篇题解!可以\(hack\)全网大部分的做法!!!
首先,我们可以把原图中的边,分成两类,一类是与\(1\)相连,另一类是不与\(1\)相连。
原题就转化成选择\(k\)条关键边的\(MST\)
那么我们可以按照tree I 那个题的思路来考虑这个题。
由于是\(MST\),所以函数满足下凸,那么对于这种恰好选\(k\)个的问题,我们可以直接凸优化。
\(erf\)一个值,然后把所有与1相连的边都加上这个值。
对于相等权值的来说,我们优先把不与1相连的边排在前面。
那么这种情况我们二分出来的那个\(mid\)
满足两个条件
1.满足下界,也就是说,能选到<=k条边的最大的\(mid\)
2.在这种情况下,\(mst\)上面的与1相连的边,是“必须出现在MST”上的边。
那么我们考虑该怎么统计方案。
首先,对于那些一定要出现在\(MST\)上的关键边,我们先把他们加入\(ans\)(只加入与1相连的边),然后对于剩下的边,把与1相连的边加上\(mid\)后,进行\(MST\),如果已经选够了\(k\)条边,那么对于剩下的关键边就直接跳过。
这样做正确的原因是,我们首先把必须要出现暗在\(MST\)上的边加入了\(ans\),然后对于剩下的边,只会分成两种,可能在MST上,或者是不可能在MST上,那剩下的部分直接用贪心的思路来做\(MST\)就是没错的。
而网上大多数题解是错的,qwq
所以这个问题困扰了我很久
#include<bits/stdc++.h>
#define pb push_back
#define mk make_pair
#define ll long long
#define int long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 3e5+1e2;
struct Edge{
int u,v;
ll w;
int tag,num;
};
Edge e[maxn];
int fa[maxn];
int n,m,k;
int val;
int find(int x)
{
if (fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
bool cmp(Edge a,Edge b)
{
if(a.w==b.w) return a.tag>b.tag;
return a.w<b.w;
}
bool cmp1(Edge a,Edge b)
{
if (a.w==b.w) return a.tag<b.tag;
return a.w<b.w;
}
int solve()
{
for (int i=1;i<=n;i++) fa[i]=i;
sort(e+1,e+1+m,cmp1);
int tot=0;
for (int i=1;i<=m;i++)
{
int f1 = find(e[i].u);
int f2 = find(e[i].v);
if (f1==f2) continue;
fa[f1]=fa[f2];
tot+=e[i].tag;
}
return tot;
}
vector<int> v;
int lyf[maxn*2];
signed main()
{
n=read(),m=read(),k=read();
ll l = -1e10,r=1e10;
int ymh=0;
for (int i=1;i<=m;i++)
{
e[i].u=read(),e[i].v=read(),e[i].w=read(),e[i].num=i;
if (e[i].u==1 || e[i].v==1) e[i].tag=1;
if (e[i].tag==1) ymh++;
}
ll ans=0;
//cout<<ymh<<endl;
while(r>=l)
{
ll mid = (l+r)/2;
for (int i=1;i<=m;i++) if(e[i].tag) e[i].w+=mid;
int tmp = solve();
//cerr<<"*"<<mid<<" "<<tmp<<endl;
if (tmp<=k) r=mid-1,ans=mid;
else l=mid+1;
for (int i=1;i<=m;i++) if (e[i].tag) e[i].w-=mid;
}
//cerr<<ans<<endl;
int ptx=0;
for (int i=1;i<=m;i++) if (e[i].tag) e[i].w+=ans;
for (int i=1;i<=n;i++) fa[i]=i;
sort(e+1,e+1+m,cmp1);
for (int i=1;i<=m;i++)
{
int f1 = find(e[i].u);
int f2 = find(e[i].v);
if (f1==f2) continue;
fa[f1]=fa[f2];
if (e[i].tag==1) lyf[e[i].num]=1;
}
for (int i=1;i<=n;i++) fa[i]=i;
for (int i=1;i<=m;i++)
{
if (lyf[e[i].num])
{
int f1 = find(e[i].u);
int f2 = find(e[i].v);
if (f1==f2) continue;
fa[f1]=fa[f2];
ptx+=e[i].tag;
v.pb(e[i].num);
}
}
//cout<<ptx<<endl;
if (ptx>k)
{
cout<<-1;
return 0;
}
//for (int i=1;i<=n;i++) fa[i]=i;
//cerr<<ptx<<endl;
sort(e+1,e+1+m,cmp);
for (int i=1;i<=m;i++)
{
int f1 = find(e[i].u);
int f2 = find(e[i].v);
if (f1==f2) continue;
if (ptx==k && e[i].tag==1) continue;
fa[f1]=fa[f2];
v.pb(e[i].num);
if (e[i].tag==1) ptx++;
}
//cerr<<ptx<<endl;
if(ptx!=k || v.size()!=n-1)
{
cout<<-1;
return 0;
}
cout<<n-1<<endl;
for (int i=0;i<v.size();i++) cout<<v[i]<<" ";
return 0;
}
//final
CF125E MST company (凸优化+MST)的更多相关文章
- 洛谷2619/bzoj2654 Tree(凸优化+MST)
bzoj的数据是真的水.. qwq 由于本人还有很多东西不是很理解 qwq 所以这里只写一个正确的做法. 首先,我们会发现,对于你选择白色边的数目,随着数目的上涨,斜率是单调升高的. 那么这时候我们就 ...
- 【CF125E】MST Company(凸优化,最小生成树)
[CF125E]MST Company(凸优化,最小生成树) 题面 洛谷 CF 题解 第一眼看见就给人丽洁姐那道\(tree\)一样的感觉. 那么二分一个权值,加给所有有一个端点是\(1\)的边, 然 ...
- luogu CF125E MST Company wqs二分 构造
LINK:CF125E MST Company 难点在于构造 前面说到了求最小值 可以二分出斜率k然后进行\(Kruskal\) 然后可以得到最小值.\(mx\)为值域. 得到最小值之后还有一个构造问 ...
- CodeForces 125E MST Company
E. MST Company time limit per test 8 seconds memory limit per test 256 megabytes input standard inpu ...
- 机器学习&数据挖掘笔记_15(关于凸优化的一些简单概念)
没有系统学过数学优化,但是机器学习中又常用到这些工具和技巧,机器学习中最常见的优化当属凸优化了,这些可以参考Ng的教学资料:http://cs229.stanford.edu/section/cs22 ...
- paper 110:凸优化和非凸优化
数学中最优化问题的一般表述是求取,使,其中是n维向量,是的可行域,是上的实值函数.凸优化问题是指是闭合的凸集且是上的凸函数的最优化问题,这两个条件任一不满足则该问题即为非凸的最优化问题. 其中,是 凸 ...
- 凸优化简介 Convex Optimization Overview
最近的看的一些内容好多涉及到凸优化,没时间系统看了,简单的了解一下,凸优化的两个基本元素分别是凸函数与凸包 凸集 凸集定义如下: 也就是说在凸集内任取两点,其连线上的所有点仍在凸集之内. 凸函数 凸函 ...
- 【Codeforces 321E / BZOJ 5311】【DP凸优化】【单调队列】贞鱼
目录 题意: 输入格式 输出格式 思路: DP凸优化的部分 单调队列转移的部分 坑点 代码 题意: 有n条超级大佬贞鱼站成一行,现在你需要使用恰好k辆车把它们全都运走.要求每辆车上的贞鱼在序列中都是连 ...
- 2019.03.12 codeforces739E. Gosha is hunting(dp凸优化)
传送门 题意:nnn个物品,有aaa个XXX道具和bbb个YYY道具,XXX道具移走第iii个物品概率为pip_ipi,YYY道具移走第iii个道具概率为uiu_iui. 对于每个物品每种道具最多 ...
随机推荐
- MySQL 常用的聚合函数
[常用的聚合函数] mysql聚合函数一般用户统计一列值进行计算,然后返回计算结果.一般于分组group by 配合使用. count //统计个数 select count(*) from test ...
- Git使用教程五
基于ssh协议(推荐) 该方式与前面https方式相比,只是影响github对于用户的身份鉴权方式,对于git的具体操作(如提交本地.添加注释.提交远程等操作)没有任何影响. 生成公私钥对指令(需 ...
- 【Azure 应用服务】Python flask 应用部署在Aure App Service 遇见的 3 个问题
在App Service(Windows)中部署Flask应用时的注意事项: ● 添加Python扩展插件,Python 3.6.4 x64: ●● 配置 FastCGI 处理程序,添加Web.con ...
- 洛谷P3104 Counting Friends G 题解
题目 [USACO14MAR]Counting Friends G 题解 这道题我们可以将 \((n+1)\) 个边依次去掉,然后分别判断去掉后是否能满足.注意到一点, \(n\) 个奶牛的朋友之和必 ...
- Linux从头学11:理解了这三个概念,才能彻底理解任务管理和任务切换
作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...
- 事务保存点savepoint
一.
- [第九篇]——Docker 镜像使用之Spring Cloud直播商城 b2b2c电子商务技术总结
Docker 镜像使用 当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载. 下面我们来学习: 1.管理 ...
- "指针"和"引用"大对比
相同点: 都能够直接引用对象,并对对象进行操作. 不同点: 指针 引用 指针类型的变量能够保存一个对象的地址 引用是一个对象的别名 可以为空nil,可以不初始化 不可以为空nil,必须初始化 当设计一 ...
- Java基础系列(38)- 数组的使用
数组的使用 For-Each循环 数组作方法入参 数组作返回值 For-Each循环 普通型 package array; import sun.security.util.Length; publi ...
- Elasticsearch2.4.6版本 在linux 命令行 对数据的增删改操作
一._cluster系列:查询设置集群状态 1.设置集群状态 curl -XGET 10.68.120.167:9204/_cluster/health?pretty=true pretty=true ...