分组赛时学到的最小乘积生成树模型,感觉这个思路非常神,可以说是数形结合的经典问题

由于生成树有两个权值,我们把每个生成树的权值表示成点坐标(sa,sb)

显然我们知道,乘积最小,那么点必然落在下凸壳上

但由于点太多,graham之类要先知道所有点再求凸包的算法就失效了

于是我们使用quickhull算法,这个算法只要知道凸包上的两个点就可以扩展出下一个点,然后不断分治即可扩展出所有点

显然,以a为关键字和以b为关键字的最小生成树一定是凸包上的两个点i,j

根据quickhull算法,下一个凸包上的点就是离直线ij距离最大的点

转化一下,就是与ij垂直的向量点积最小的点

显然我们只要以此为关键字求最小生成树即可

这样我们不断分治下去,直到无法扩展为止,这样就找到了答案

但我好像被卡常了(还是写的太囧……),总之tle了……

  1. type node=record
  2. x,y,w,a,b:longint;
  3. end;
  4. point=record
  5. x,y:longint;
  6. end;
  7.  
  8. var e:array[..] of node;
  9. fa:array[..] of longint;
  10. i,n,m:longint;
  11. ans,p1,p2:point;
  12.  
  13. function getf(x:longint):longint;
  14. begin
  15. if fa[x]<>x then fa[x]:=getf(fa[x]);
  16. exit(fa[x]);
  17. end;
  18.  
  19. procedure swap(var a,b:node);
  20. var c:node;
  21. begin
  22. c:=a;
  23. a:=b;
  24. b:=c;
  25. end;
  26.  
  27. function cmp(x,y:node):boolean;
  28. begin
  29. if x.w=y.w then exit(x.a<y.a);
  30. exit(x.w<y.w);
  31. end;
  32.  
  33. procedure sort(l,r:longint);
  34. var i,j:longint;
  35. x:node;
  36. begin
  37. i:=l;
  38. j:=r;
  39. x:=e[(l+r) shr ];
  40. repeat
  41. while cmp(e[i],x) do inc(i);
  42. while cmp(x,e[j]) do dec(j);
  43. if not(i>j) then
  44. begin
  45. swap(e[i],e[j]);
  46. inc(i);
  47. dec(j);
  48. end;
  49. until i>j;
  50. if l<j then sort(l,j);
  51. if i<r then sort(i,r);
  52. end;
  53.  
  54. function mintree:point;
  55. var i,j,sa,sb,x,y:longint;
  56. begin
  57. {for j:=1 to m do
  58. writeln(e[j].w); }
  59. j:=;
  60. sa:=;
  61. sb:=;
  62. for i:= to n do
  63. fa[i]:=i;
  64. i:=;
  65. while i<n- do
  66. begin
  67. inc(j);
  68. x:=getf(e[j].x);
  69. y:=getf(e[j].y);
  70. if x<>y then
  71. begin
  72. fa[x]:=y;
  73. sa:=sa+e[j].a;
  74. sb:=sb+e[j].b;
  75. inc(i);
  76. end;
  77. end;
  78. mintree.x:=sa;
  79. mintree.y:=sb;
  80. 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
  81. begin
  82. ans.x:=sa;
  83. ans.y:=sb;
  84. end;
  85. end;
  86.  
  87. function cross(a,b,c:point):int64;
  88. begin
  89. exit(int64(a.x-c.x)*int64(b.y-c.y)-int64(a.y-c.y)*int64(b.x-c.x));
  90. end;
  91.  
  92. procedure work(p1,p2:point);
  93. var i:longint;
  94. p:point;
  95.  
  96. begin
  97. for i:= to m do
  98. e[i].w:=e[i].a*(p1.y-p2.y)+e[i].b*(p2.x-p1.x);
  99. sort(,m);
  100. p:=mintree;
  101. if cross(p2,p,p1)>= then exit;
  102. work(p1,p);
  103. work(p,p2);
  104. end;
  105.  
  106. begin
  107. readln(n,m);
  108. for i:= to m do
  109. begin
  110. readln(e[i].x,e[i].y,e[i].a,e[i].b);
  111. inc(e[i].x);
  112. inc(e[i].y);
  113. e[i].w:=e[i].a;
  114. end;
  115. ans.x:=;
  116. ans.y:=;
  117. sort(,m);
  118. p1:=mintree;
  119. for i:= to m do
  120. e[i].w:=e[i].b;
  121. sort(,m);
  122. p2:=mintree;
  123. work(p1,p2);
  124. writeln(ans.x,' ',ans.y);
  125. end.

bzoj2395的更多相关文章

  1. 【BZOJ2395】[Balkan 2011]Timeismoney

    [BZOJ2395][Balkan 2011]Timeismoney 题面 \(darkbzoj\) 题解 如果我们只有一个条件要满足的话直接最小生成树就可以了,但是现在我们有两维啊... 我们将每个 ...

  2. 【最小乘积生成树】bzoj2395[Balkan 2011]Timeismoney

    设每个点有x,y两个权值,求一棵生成树,使得sigma(x[i])*sigma(y[i])最小. 设每棵生成树为坐标系上的一个点,sigma(x[i])为横坐标,sigma(y[i])为纵坐标.则问题 ...

  3. BZOJ2395 [Balkan 2011]Timeismoney 【最小乘积生成树】

    题目链接 BZOJ2395 题意:无向图中每条边有两种权值,定义一个生成树的权值为两种权值各自的和的积 求权值最小的生成树 题解 如果我们将一个生成树的权值看做坐标,那么每一个生成树就对应一个二维平面 ...

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

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

  5. bzoj2395: [Balkan 2011]Timeismoney

    Description      有n个城市(编号从0..n-1),m条公路(双向的),从中选择n-1条边,使得任意的两个城市能够连通,一条边需要的c的费用和t的时间,定义一个方案的权值v=n-1条边 ...

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

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

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

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

  8. BZOJ2395:[Balkan 2011]Timeismoney——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=2395 有n个城市(编号从0..n-1),m条公路(双向的),从中选择n-1条边,使得任意的两个城市 ...

  9. bzoj2395 [Balkan 2011]Timeismoney(最小乘积生成树+计算几何)

    题意 每条边有两个权值\(c,t\),请求出一颗生成树,使得\(\sum c\times \sum t\)最小 题解 为什么生成树会和计算几何扯上关系-- 对于每棵树,设\(x=c,y=t\),我们可 ...

随机推荐

  1. Handlebars模板引擎中的each嵌套及源码浅读

    若显示效果不佳,可移步到愚安的小窝 Handlebars模板引擎作为时下最流行的模板引擎之一,已然在开发中为我们提供了无数便利.作为一款无语义的模板引擎,Handlebars只提供极少的helper函 ...

  2. bnuoj 4209 Triangle(计算几何)

    http://www.bnuoj.com/bnuoj/problem_show.php?pid=4209 题意:如题 题解:公式直接计算,或者角平分线求交点 [code1]: #include < ...

  3. android 自定义ratingbar 图片显示不全的解决方案

    在res/style中自定义评分条: <!-- 自定义评分条 --> <style name="roomRatingBar" parent="@andr ...

  4. web服务器和应用服务器

    通俗的讲,Web服务器传送(serves)页面使浏览器可以浏览,然而应用程序服务器提供的是客户端应用程序可以调用(call)的方法(methods).确切一点,你可以说:Web服务器专门处理HTTP请 ...

  5. 用windows远程连接linux桌面(使用tightvnc或者tigervnc)

    一.安装tightvnc: tightvnc的安装在安装包中有详细的说明(README文件) 首先你要确保linux已经安装jpeg和zlib库, 2.编译 执行如下两个命令: [root@local ...

  6. 【Unity3D】iOS 推送实现

    原地址:http://www.iappfan.com/%E3%80%90unity3d%E3%80%91ios-%E6%8E%A8%E9%80%81%E5%AE%9E%E7%8E%B0/ #impor ...

  7. What is the difference between Views and Materialized Views in Oracle?

    aterialized views are disk based and update periodically base upon the query definition. Views are v ...

  8. hdu 3441 Rotation

    总的来说,这题要2次用到polya定理. 由题目条件A*A=B*B+1,变形为(A-1)*(A+1)=K*B*B; 分别分解A-1和A+1的质因数,在合并在一起. 第一步:搜索B,对B*B的正方形涂色 ...

  9. [2-sat]HDOJ3062 Party

    中文题 题意略 学2-sat啦啦啦 2-sat就是    矛盾的 ($x.x’$不能同时取) m对人 相互也有限制条件 取出其中n个人 也有可能是把一件东西分成 取/不取 相矛盾的两种情况 (那就要拆 ...

  10. hihocoder 1084 扩展KMP && 2014 北京邀请赛 Justice String

    hihocoder 1084 : http://hihocoder.com/problemset/problem/1084 北京邀请赛 Just  String http://www.bnuoj.co ...