洛谷 P5540 - [BalkanOI2011] timeismoney | 最小乘积生成树(最小生成树)
大概是一个比较 trivial 的小 trick?学过了就不要忘了哦(
莫名奇妙地想到了 yyq 的”hot tea 不常有,做过了就不能再错过了“
首先看到这种二维问题我们可以很自然地想到将它们映射到一个二维平面上,即我们将 \(\sum\limits_{e\in E}a_e\) 看作横坐标 \(x\),将 \(\sum\limits_{e\in E}b_e\) 看作纵坐标 \(y\),那么我们所求即是全部生成树表示的点当中横纵坐标之积最大的点。显然这些点肯定都在所有点组成的下凸壳上,因此我们只用求出下凸壳上的所有点然后依次更新答案即可。
那么怎么求下凸壳上的点呢?我们考虑分治,考虑求出所有点当中横坐标最小的点 \(A\) 和纵坐标最小的点 \(B\)——这个可以通过将边权赋为 \(a_e\) 和 \(b_e\) 分别求一遍最小生成树求出,那么我们考虑求出满足 \(C\) 在 \(AB\) 左下方且 \(S_{\triangle ABC}\) 最大的点 \(C\)——由于 \(C\) 在 \(AB\) 左下方,根据计算几何那一套理论,\(S_{\triangle ABC}\) 最大即意味着 \(\vec{BA}\times\vec{BC}\) 最大,而 \(\vec{BA}\times\vec{BC}=(x_A-x_B)(y_C-y_B)-(x_C-x_B)(y_A-y_B)\),将括号打开,与 \(C\) 无关的放一边可以得到 \(\vec{BA}\times\vec{BC}\) 最大又意味着 \((x_A-x_B)y_C-(y_A-y_B)x_C\) 最大,因此考虑将每条边边权赋为 \((x_B-x_A)b_e-(y_A-y_B)a_e\) 然后跑一遍 MST 即可求出点 \(C\),如果我们发现求出的点 \(C\) 在 \(AB\) 右上方那直接 return 掉即可,否则继续递归处理 \((A,C)\) 和 \((C,B)\)。
据说用了个什么 QuickHull 的求凸包算法,凸壳上的点数最多是值域的 \(\dfrac{2}{3}\) 次方,因此复杂度就是 \((na)^{2/3}·n\log n\),但是显然证明就不是我的事了(
不知道能不能推广到三维.jpg
const int MAXN=200;
const int MAXM=1e4;
struct edge{int u,v,w;} e[MAXM+5];
int n,m,a[MAXM+5],b[MAXM+5],f[MAXN+5];
int find(int x){return (!f[x])?x:f[x]=find(f[x]);}
void merge(int x,int y){x=find(x);y=find(y);f[x]=y;}
int ord[MAXM+5];pii ans=mp(0x3f3f3f3f,0x3f3f3f3f);
bool cmp(int x,int y){return e[x].w<e[y].w;}
pii kruskal(){
memset(f,0,sizeof(f));for(int i=1;i<=m;i++) ord[i]=i;
sort(ord+1,ord+m+1,cmp);int suma=0,sumb=0;
for(int i=1;i<=m;i++){
if(find(e[ord[i]].u)==find(e[ord[i]].v)) continue;
merge(e[ord[i]].u,e[ord[i]].v);
suma+=a[ord[i]];sumb+=b[ord[i]];
} if(1ll*suma*sumb<1ll*ans.fi*ans.se||(1ll*suma*sumb==1ll*ans.fi*ans.se&&suma<ans.fi))
ans=mp(suma,sumb);
return mp(suma,sumb);
}
void solve(pii x,pii y){
for(int i=1;i<=m;i++) e[i].w=b[i]*(y.fi-x.fi)+a[i]*(x.se-y.se);pii z=kruskal();
if(1ll*(x.fi-y.fi)*(x.se-z.se)-1ll*(x.se-y.se)*(x.fi-z.fi)>=0) return;
solve(x,z);solve(z,y);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&e[i].u,&e[i].v,&a[i],&b[i]);
++e[i].u;++e[i].v;
} pii x,y;
for(int i=1;i<=m;i++) e[i].w=a[i];x=kruskal();
for(int i=1;i<=m;i++) e[i].w=b[i];y=kruskal();
solve(x,y);printf("%d %d\n",ans.fi,ans.se);
return 0;
}
洛谷 P5540 - [BalkanOI2011] timeismoney | 最小乘积生成树(最小生成树)的更多相关文章
- bzoj2395[Balkan 2011]Timeismoney最小乘积生成树
所谓最小乘积生成树,即对于一个无向连通图的每一条边均有两个权值xi,yi,在图中找一颗生成树,使得Σxi*Σyi取最小值. 直接处理问题较为棘手,但每条边的权值可以描述为一个二元组(xi,yi),这也 ...
- 【BZOJ2395】【Balkan 2011】Timeismoney 最小乘积生成树
链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网 ...
- Bzoj2395: [Balkan 2011]Timeismoney(最小乘积生成树)
问题描述 每条边两个权值 \(x,y\),求一棵 \((\sum x) \times (\sum y)\) 最小的生成树 Sol 把每一棵生成树的权值 \(\sum x\) 和 \(\sum y\) ...
- P5540-[BalkanOI2011]timeismoney|最小乘积生成树【最小生成树,凸壳】
正题 题目链接:https://www.luogu.com.cn/problem/P5540 题目大意 给出\(n\)个点\(m\)条边边权是一个二元组\((a_i,b_i)\),求出一棵生成树最小化 ...
- bzoj 2395 [Balkan 2011]Timeismoney——最小乘积生成树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2395 如果把 \( \sum t \) 作为 x 坐标,\( \sum c \) 作为 y ...
- bzoj 2395 Timeismoney —— 最小乘积生成树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2395 参考博客:https://www.cnblogs.com/autsky-jadek/p ...
- Luogu5540 最小乘积生成树
Luogu5540 最小乘积生成树 题目链接:洛谷 题目描述:对于一个\(n\)个点\(m\)条边的无向连通图,每条边有两个边权\(a_i,b_i\),求使\((\sum a_i)\times (\s ...
- HDU5697 刷题计划 dp+最小乘积生成树
分析:就是不断递归寻找靠近边界的最优解 学习博客(必须先看这个): 1:http://www.cnblogs.com/autsky-jadek/p/3959446.html 2:http://blog ...
- 洛谷P4014 分配问题【最小/大费用流】题解+AC代码
洛谷P4014 分配问题[最小/大费用流]题解+AC代码 题目描述 有 n 件工作要分配给 n 个人做.第 i 个人做第 j 件工作产生的效益为c ij. 试设计一个将 n 件工作分配给 n 个人做的 ...
随机推荐
- python3去除行号
问题:在复制一些代码时会同时复制每行的行号,删除比较麻烦,所以利用python3本身的代码进行一键删除. # 导入re 模块来使用正则表达式 import re """去 ...
- 初学python-day3 元组
day2 列表已更新!
- 大闸蟹的 O O 第三单元日子——中测与强测的惨烈修罗场
第三单元是大闸蟹体验及其差的一单元,鬼知道从一开始的自信慢慢到最后的自暴自弃我都经历了什么,我已经感觉到分数与gpa与头发都在渐渐和我说再见了 JML基础梳理及工具链 JML(Java Modelin ...
- BUAA 软件工程个人作业
BUAA 软件工程 个人项目作业 Author: 17373015 乔玺华 教学班级 :005 项目地址:https://github.com/JordenQiao/SE_Homework_Perso ...
- 用cmd命令行创建vue项目模板
1.进入cmd命令行 输入存放项目的位置 2.通过vue create 项目名称 创建项目 3.选择Manually select features 4.通过空格选中第1.2.5.6.7.去掉8 4. ...
- 常见SOC启动流程分析
本文以s5pv210这款SOC为例,分析了其启动流程 在s5pv210的SOC内部,存在着一个内部的ROM和一个内部的RAM 这个内部的ROM叫做 IROM,它是norflash的一种.其不同于板子上 ...
- Python常用的数据文件存储的4种格式(txt/json/csv/excel)及操作Excel相关的第三方库(xlrd/xlwt/pandas/openpyxl)(2021最新版)
序言:保存数据的方式各种各样,最简单的方式是直接保存为文本文件,如TXT.JSON.CSV等,除此之外Excel也是现在比较流行的存储格式,通过这篇文章你也将掌握通过一些第三方库(xlrd/xlwt/ ...
- 解决mac主机无法与 Docker容器互通问题
方法很多,这里我说一下使用 docker-connector解决这个问题 这是一个github开源项目docker-connector 1. Mac 通过 brew 安装 docker-connec ...
- Maven settings配置阿里镜像
一般只用配置三个地方 maven仓库路径 镜像 默认JDK版本 <?xml version="1.0" encoding="UTF-8"?> < ...
- uni-城市列表滑动组件,点击字母跳转到指定位置
本插件由博主自主开发,比uni插件市场的城市列表滑动组件性能好,且不会出现闪屏的情况. 通过计算城市列表的高度实现滚动到指定位置,使用了uni滚动到指定位置的api city-chooce为页面入口页 ...