洛谷题面传送门

大概是一个比较 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 | 最小乘积生成树(最小生成树)的更多相关文章

  1. bzoj2395[Balkan 2011]Timeismoney最小乘积生成树

    所谓最小乘积生成树,即对于一个无向连通图的每一条边均有两个权值xi,yi,在图中找一颗生成树,使得Σxi*Σyi取最小值. 直接处理问题较为棘手,但每条边的权值可以描述为一个二元组(xi,yi),这也 ...

  2. 【BZOJ2395】【Balkan 2011】Timeismoney 最小乘积生成树

    链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网 ...

  3. Bzoj2395: [Balkan 2011]Timeismoney(最小乘积生成树)

    问题描述 每条边两个权值 \(x,y\),求一棵 \((\sum x) \times (\sum y)\) 最小的生成树 Sol 把每一棵生成树的权值 \(\sum x\) 和 \(\sum y\) ...

  4. P5540-[BalkanOI2011]timeismoney|最小乘积生成树【最小生成树,凸壳】

    正题 题目链接:https://www.luogu.com.cn/problem/P5540 题目大意 给出\(n\)个点\(m\)条边边权是一个二元组\((a_i,b_i)\),求出一棵生成树最小化 ...

  5. bzoj 2395 [Balkan 2011]Timeismoney——最小乘积生成树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2395 如果把 \( \sum t \) 作为 x 坐标,\( \sum c \) 作为 y ...

  6. bzoj 2395 Timeismoney —— 最小乘积生成树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2395 参考博客:https://www.cnblogs.com/autsky-jadek/p ...

  7. Luogu5540 最小乘积生成树

    Luogu5540 最小乘积生成树 题目链接:洛谷 题目描述:对于一个\(n\)个点\(m\)条边的无向连通图,每条边有两个边权\(a_i,b_i\),求使\((\sum a_i)\times (\s ...

  8. HDU5697 刷题计划 dp+最小乘积生成树

    分析:就是不断递归寻找靠近边界的最优解 学习博客(必须先看这个): 1:http://www.cnblogs.com/autsky-jadek/p/3959446.html 2:http://blog ...

  9. 洛谷P4014 分配问题【最小/大费用流】题解+AC代码

    洛谷P4014 分配问题[最小/大费用流]题解+AC代码 题目描述 有 n 件工作要分配给 n 个人做.第 i 个人做第 j 件工作产生的效益为c ij. 试设计一个将 n 件工作分配给 n 个人做的 ...

随机推荐

  1. 【java】【作业】定义课程信息;继承和组合练习

    问题: 定义课程信息类,包含课程编号.课程名称及学生成绩.编程实现对软件工程专业的某班级的所有课程成绩统计,包括平均成绩.最高成绩.最低成绩,并打印成绩等级分布律. 分析 初分析: 父类(课程信息类) ...

  2. Spark RDD编程(博客索引,日常更新)

    本篇主要是记录自己在中解决RDD编程性能问题中查阅的论文博客,为我认为写的不错的建立索引方便查阅,我的总结会另立他篇 1)通过分区(Partitioning)提高spark性能https://blog ...

  3. 初学python-day6 for循环和流程控制(已更新循环做三角形图形!!)

    for循环 1.格式 for    变量    in   集合: 循环体 2.概述 当程序执行for循环,按顺序从集合中获取元素变量保存当前循环得到的值,再去执行循环体.当集合中数据都被取完,则此刻跳 ...

  4. Hadoop集群的配置(一)

    摘要: hadoop集群配置系列文档,是笔者在实验室真机环境实验后整理而得.以便随后工作所需,做以知识整理,另则与博客园朋友分享实验成果,因为笔者在学习初期,也遇到不少问题.但是网上一些文档大多互相抄 ...

  5. Manjaro安装Mariadb

    Mariadb是MySQL的一个复刻.由于MySQL被Oracle公司收购,MySQL的一些原始开发者担心MySQL会有开源方面的某些隐患,故领导开发了Mariadb. 如今,Mariadb已经作为许 ...

  6. [技术博客]OKhttp3使用get,post,delete,patch四种请求

    OKhttp3使用get,post,delete,patch四种请求 1.okhttp简介 okhttp封装了大量http操作,大大简化了安卓网络请求操作,是现在最火的安卓端轻量级网络框架.如今okh ...

  7. OO第二单元——多线程(电梯)

    OO第二单元--多线程(电梯) 综述 第二单元的三次联系作业都写电梯,要求逐步提高,对于多线程的掌握也进一步加深.本次作业全部都给出了输入输出文件,也就避免了正则表达式判断输入输出是否合法的问题. 第 ...

  8. CSP/S 2020 退役记

    上一次的AFO记 上上次的AFO记 Day -INF 一条咸鱼的垂死挣扎. RP+=INF Day 0 出发辣. 早上来到机房,带上了准备的面包和泡面....然而后来嫌太占地方就没拿...草了. 而且 ...

  9. 洛谷 P4774 [NOI2018] 屠龙勇士

    链接:P4774 前言: 交了18遍最后发现是多组数据没清空/ll 题意: 其实就是个扩中. 分析过程: 首先发现根据题目描述的选择剑的方式,每条龙对应的剑都是固定的,有查询前驱,后继(在该数不存在前 ...

  10. Python中根据时间自动创建文件夹

    导语 ​ 电脑桌面文件太多查找起来比较花费时间,并且凌乱的电脑桌面也会影响工作心情,于是利用python根据时间自动建立当日文件夹,这样就可以把桌面上文件按时间进行存放. 代码实现 # _*_codi ...