• 最小乘积生成树


      1 type
      2 ans=record
      3 p,q:longint;
      4 end;
      5 var
      6 s,u,v,x,y:array[0..10000] of longint;
      7 f:array[0..200] of longint;
      8 i,j,k,n:longint;
      9 anss,ans1,ans2:ans;
     10 o1,o2:int64;
     11 procedure swap(var x,y:longint);
     12 var
     13 w:longint;
     14 begin
     15     w:=x; x:=y; y:=w;
     16 end;
     17 procedure sort(l,r:longint);
     18 var
     19 w,mid,i,j:longint;
     20 begin
     21     i:=l; j:=r;
     22     mid:=s[(l+r) div 2];
     23     repeat
     24       while s[i]<mid do
     25         inc(i);
     26       while s[j]>mid do
     27         dec(j);
     28       if not(i>j) then
     29       begin
     30           swap(s[i],s[j]);
     31           swap(u[i],u[j]);
     32           swap(v[i],v[j]);
     33           swap(x[i],x[j]);
     34           swap(y[i],y[j]);
     35           inc(i);
     36           dec(j);
     37       end;
     38     until i>j;
     39     if l<j then sort(l,j);
     40     if i<r then sort(i,r);
     41 end;
     42 function find(x:longint):longint;
     43 begin
     44     if f[x]=x then exit(x);
     45     find:=find(f[x]);
     46     f[x]:=find;
     47 end;
     48 function kl:ans;
     49 var
     50 t,fx,fy,i:longint;
     51 sum:ans;
     52 begin
     53     sort(1,k);
     54     for i:=1 to n do f[i]:=i;
     55     sum.p:=0; sum.q:=0; t:=0;
     56     for i:=1 to k do
     57     begin
     58         fx:=find(x[i]);
     59         fy:=find(y[i]);
     60         if fx<>fy then
     61         begin
     62             f[fx]:=fy;
     63             inc(t);
     64             sum.p:=sum.p+u[i];
     65             sum.q:=sum.q+v[i];
     66             if t=n-1 then
     67             break;
     68         end;
     69     end;
     70     o1:=anss.p*anss.q;
     71     o2:=sum.p*sum.q;
     72     if (o1>o2)or((o1=o2)and(anss.p>sum.p)) then
     73     anss:=sum;
     74     kl:=sum;
     75 end;
     76 procedure solve(a,b:ans);
     77 var
     78 aa,bb,cc,i:longint;
     79 c:ans;
     80 begin
     81     aa:=(a.q-b.q);   bb:=(b.p-a.p);  cc:=a.p*b.q-a.q*b.p;
     82     for i:=1 to k do
     83         s[i]:=u[i]*aa+v[i]*bb;
     84     c:=kl;
     85     if c.p*aa+c.q*bb+cc>=0 then exit;
     86     solve(a,c);
     87     solve(c,b);
     88 end;
     89 begin
     90     read(n,k);
     91     for i:=1 to k do
     92     begin
     93         read(x[i],y[i],u[i],v[i]);
     94         inc(x[i]); inc(y[i]);
     95     end;
     96     anss.p:=trunc(sqrt(maxlongint)); anss.q:=trunc(sqrt(maxlongint));
     97     s:=u; ans1:=kl;
     98     s:=v; ans2:=kl;
     99     solve(ans1,ans2);
    100     writeln(anss.p,' ',anss.q);
    101 end.
    102 
    View Code

    (bzoj 2395)

    一般的,这种题型会给你两个参数a[i],b[i],先分别根据以a[i]与b[i]做最小生成树,得到最靠近X轴与Y轴的点。

    因为题目要求∑a[i]*∑b[j]最小,也就是反比例函数y=k/x中的k最小,我们每次可以选择离直线最远的点。

    但是我刚学向量不久,还不会叉积,于是只能用点到直线距离的公式。。。

    每次求出两个边界点直线的解析式 ax+by+c=0;

    由(x1,y1),(x2,y2) ;

    可算出a=(y1-y2); b=(x2-x1); c=x1*y2-x2*y1;

    直线到点(x,y)的距离为:a*x+b*y+c/√(a^2+b^2)

    所以可以算出每个点到直线的距离大小又因为与点有关的是x,y,所以只要比较(a*x+b*y)的大小再进行排序

    就求出了可能更优的边,再一直递归去求可能更优的点。

    但递归边界是什么呢?

    当求出的最优点在直线外侧时

      

    很显然,当a*x+b*y+c>=0时

    这一定没有A.B优,这时就可以退出了

  • 相关阅读:
    团队展示
    第二次结对编程作业
    第12组 团队展示
    第一次结对编程作业
    第一次个人编程作业
    软工第一次作业
    第十章 创建计算字段
    第九章 用正则表达式进行搜索
    第八章 用通配符进行过滤
    第七章 数据过滤
  • 原文地址:https://www.cnblogs.com/fhlxpyz/p/6627031.html
Copyright © 2020-2023  润新知