洛谷 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 个人做的 ...
随机推荐
- nexus设置npm下载管理
nexus设置npm下载管理 第一步 登录私服网页 第二步 创建存储空间(如果使用默认的存储空间,此步骤可省略) 第三步 输入空间的名称,点击create创建 第四步 创建仓库 npm的仓库有三种: ...
- Less-23 preg_replace1
Less-23: 直接跳到Less-23的原因是,Less-(11~22)均为注入点不为get方式的注入.我先把get型注入写的差不多,再回来整理关于注入点的内容. 核心语句: 查询.报错均有回显. ...
- k8s replicaset controller分析(2)-核心处理逻辑分析
replicaset controller分析 replicaset controller简介 replicaset controller是kube-controller-manager组件中众多控制 ...
- the Agiles Scrum Meeting 8
会议时间:2020.4.16 20:00 1.每个人的工作 今天已完成的工作 个人结对项目增量开发组:完成个人项目创建的部分功能 issues:增量组:准备评测机制,增加仓库自动创建和管理 团队项目增 ...
- 【二食堂】Alpha - 测试报告
TextMarking Alpha阶段测试报告 前后端测试过程及结果 在Alpha阶段,测试工作紧跟后端开发进度,一下是我们所做的一些测试工作. 后端单元测试 测试代码可以在git仓库中查看,后端对所 ...
- [软工作业]-软件案例分析-CSDN
[软工作业]-软件案例分析-CSDN(app) 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人博客作业-软件案例分析 我在这个课程的目标是 ...
- Spring Cloud Gateway GatewayFilter的使用
Spring Cloud Gateway GatewayFilter的使用 一.GatewayFilter的作用 二.Spring Cloud Gateway内置的 GatewayFilter 1.A ...
- Golang通脉之并发初探
并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发. 并发与并行 并发:同一时间段内执行多个任务. 并行:同一时刻执行多个任务,有时间上的重叠. 进程.线程.协程 进程(Process) ...
- sql关联修改
UPDATE p set p.ClientID = c.id from PaymentTable p left JOIN ClientTable c on p.ClientID = c.Clie ...
- 大爽Python入门教程 2-1 认识容器
大爽Python入门公开课教案 点击查看教程总目录 1 什么是容器 先思考这样一个场景: 有五个学生,姓名分别为: Alan, Bruce, Carlos, David, Emma. 需要给他们都打一 ...