bzoj2395
分组赛时学到的最小乘积生成树模型,感觉这个思路非常神,可以说是数形结合的经典问题
由于生成树有两个权值,我们把每个生成树的权值表示成点坐标(sa,sb)
显然我们知道,乘积最小,那么点必然落在下凸壳上
但由于点太多,graham之类要先知道所有点再求凸包的算法就失效了
于是我们使用quickhull算法,这个算法只要知道凸包上的两个点就可以扩展出下一个点,然后不断分治即可扩展出所有点
显然,以a为关键字和以b为关键字的最小生成树一定是凸包上的两个点i,j
根据quickhull算法,下一个凸包上的点就是离直线ij距离最大的点
转化一下,就是与ij垂直的向量点积最小的点
显然我们只要以此为关键字求最小生成树即可
这样我们不断分治下去,直到无法扩展为止,这样就找到了答案
但我好像被卡常了(还是写的太囧……),总之tle了……
type node=record
x,y,w,a,b:longint;
end;
point=record
x,y:longint;
end; var e:array[..] of node;
fa:array[..] of longint;
i,n,m:longint;
ans,p1,p2:point; function getf(x:longint):longint;
begin
if fa[x]<>x then fa[x]:=getf(fa[x]);
exit(fa[x]);
end; procedure swap(var a,b:node);
var c:node;
begin
c:=a;
a:=b;
b:=c;
end; function cmp(x,y:node):boolean;
begin
if x.w=y.w then exit(x.a<y.a);
exit(x.w<y.w);
end; procedure sort(l,r:longint);
var i,j:longint;
x:node;
begin
i:=l;
j:=r;
x:=e[(l+r) shr ];
repeat
while cmp(e[i],x) do inc(i);
while cmp(x,e[j]) do dec(j);
if not(i>j) then
begin
swap(e[i],e[j]);
inc(i);
dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; function mintree:point;
var i,j,sa,sb,x,y:longint;
begin
{for j:=1 to m do
writeln(e[j].w); }
j:=;
sa:=;
sb:=;
for i:= to n do
fa[i]:=i;
i:=;
while i<n- do
begin
inc(j);
x:=getf(e[j].x);
y:=getf(e[j].y);
if x<>y then
begin
fa[x]:=y;
sa:=sa+e[j].a;
sb:=sb+e[j].b;
inc(i);
end;
end;
mintree.x:=sa;
mintree.y:=sb;
if (int64(ans.x)*int64(ans.y)>int64(sa)*int64(sb)) or (int64(ans.x)*int64(ans.y)=int64(sa)*int64(sb)) and (ans.x>sa) then
begin
ans.x:=sa;
ans.y:=sb;
end;
end; function cross(a,b,c:point):int64;
begin
exit(int64(a.x-c.x)*int64(b.y-c.y)-int64(a.y-c.y)*int64(b.x-c.x));
end; procedure work(p1,p2:point);
var i:longint;
p:point; begin
for i:= to m do
e[i].w:=e[i].a*(p1.y-p2.y)+e[i].b*(p2.x-p1.x);
sort(,m);
p:=mintree;
if cross(p2,p,p1)>= then exit;
work(p1,p);
work(p,p2);
end; begin
readln(n,m);
for i:= to m do
begin
readln(e[i].x,e[i].y,e[i].a,e[i].b);
inc(e[i].x);
inc(e[i].y);
e[i].w:=e[i].a;
end;
ans.x:=;
ans.y:=;
sort(,m);
p1:=mintree;
for i:= to m do
e[i].w:=e[i].b;
sort(,m);
p2:=mintree;
work(p1,p2);
writeln(ans.x,' ',ans.y);
end.
bzoj2395的更多相关文章
- 【BZOJ2395】[Balkan 2011]Timeismoney
[BZOJ2395][Balkan 2011]Timeismoney 题面 \(darkbzoj\) 题解 如果我们只有一个条件要满足的话直接最小生成树就可以了,但是现在我们有两维啊... 我们将每个 ...
- 【最小乘积生成树】bzoj2395[Balkan 2011]Timeismoney
设每个点有x,y两个权值,求一棵生成树,使得sigma(x[i])*sigma(y[i])最小. 设每棵生成树为坐标系上的一个点,sigma(x[i])为横坐标,sigma(y[i])为纵坐标.则问题 ...
- BZOJ2395 [Balkan 2011]Timeismoney 【最小乘积生成树】
题目链接 BZOJ2395 题意:无向图中每条边有两种权值,定义一个生成树的权值为两种权值各自的和的积 求权值最小的生成树 题解 如果我们将一个生成树的权值看做坐标,那么每一个生成树就对应一个二维平面 ...
- bzoj2395[Balkan 2011]Timeismoney最小乘积生成树
所谓最小乘积生成树,即对于一个无向连通图的每一条边均有两个权值xi,yi,在图中找一颗生成树,使得Σxi*Σyi取最小值. 直接处理问题较为棘手,但每条边的权值可以描述为一个二元组(xi,yi),这也 ...
- bzoj2395: [Balkan 2011]Timeismoney
Description 有n个城市(编号从0..n-1),m条公路(双向的),从中选择n-1条边,使得任意的两个城市能够连通,一条边需要的c的费用和t的时间,定义一个方案的权值v=n-1条边 ...
- 【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\) ...
- BZOJ2395:[Balkan 2011]Timeismoney——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2395 有n个城市(编号从0..n-1),m条公路(双向的),从中选择n-1条边,使得任意的两个城市 ...
- bzoj2395 [Balkan 2011]Timeismoney(最小乘积生成树+计算几何)
题意 每条边有两个权值\(c,t\),请求出一颗生成树,使得\(\sum c\times \sum t\)最小 题解 为什么生成树会和计算几何扯上关系-- 对于每棵树,设\(x=c,y=t\),我们可 ...
随机推荐
- 【转】获取android设备 id
关于本文档 Android的开发者在一些特定情况下都需要知道手机中的唯一设备ID.例如,跟踪应用程序的安装,生成用于复制保护的DRM时需要使用设备的唯一ID.在本文档结尾处提供了作为参考的示例代码片段 ...
- sqlserver 2008r2 表分区拆分问题
问题描述: 对tab1表实行自动天分区,每天通过sqlserver代理-作业00:00点自动生成分区: 因有次停了数据库服务,sqlserver 代理服务忘记开启,导致当天00:00没有生成新分区: ...
- VIM配置自动提示功能
问题描述: 使用VIM作为Linux下的IDE,但是VIM默认情况下不支持自动代码提示功能,因此希望安装插件实现自动提示功能,目前找到的自动提示工具,非常好用 ...
- 【BZOJ】【1085】【SCOI2005】骑士精神
IDA*算法 Orz HZWER A*+迭代加深搜索=IDA* 这题的估价相当于一个可行性剪枝,即如果当前走的步数s+未归位的点数>搜索深度k,则剪枝 /******************** ...
- javascript积累
本来是java程序员,但是工作过程中总是遇到各种js的任务得完成,所以也得慢慢积累啊! 一.浏览器对象模型(Browser Object Model)BOM window对象:当前浏览器窗口 ...
- [转载]关于C++ const 的全面总结
C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,本人根据各方面查到的资料进行总结如下,期望对朋友们有所帮助. Const 是C++中常用的类型修饰符,常类型是指使用类 ...
- 关于去哪儿网的UI自动化测试脚本(Python实现)
UI自动化测试Qunar机票搜索场景访问Qunar机票首页http://flight.qunar.com,选择“单程”,输入出发.到达城市,选择today+7日后的日期,点“搜索”,跳转到机票单程搜索 ...
- UVA 11806 Cheerleaders (组合+容斥原理)
自己写的代码: #include <iostream> #include <stdio.h> #include <string.h> /* 题意:相当于在一个m*n ...
- php集成开发环境的安装以及Zend Studio开发工具的安装
一.集成开发环境: wampserver 下载地址: 官网: http://www.wampserver.com/ 直接下载 http://sourceforge.net/projects/wamps ...
- Python新式类和旧式类的区别
新式类是为了统一**而在2.2中开始引入的. 代码讲解 上面的例子比较明白的说明了问题. B是定义的新式类.那么输入b的时候,不论是type(b),还是b.__class__都是输出的<clas ...