bzoj 3943 最大生成树

题意:给定n个数,每次任选两个数,将这两个数的xor累加到ans里并删除其中一个数,重复操作直到只剩一个数,求ans的最大值

...一开始sb的写了个暴力贪心,在改了1h对拍后才发现naive的贪错了...

于是果断放弃挣扎

如果把比赛的两个人之间连边的话,n-1次操作后就会得到一棵树,实质上一棵树就对应着一种比赛的安排方案

那么这题实际上就是求n*(n-1)边、n个点的最大生成树,边权为两个端点的xor值

type
        rec=record
            x,y,len:longint;
end;

var
        n,tt,tot,tx,ty  :longint;
        i,j             :longint;
        ans             :int64;
        l               :array[0..4000010] of rec;
        father,a        :array[0..2010] of longint;

function get_father(x:longint):longint;
begin
   if x=father[x] then exit(x);
   father[x]:=get_father(father[x]);
   exit(father[x]);
end;

procedure sort(ll,rr:longint);
var
        i,j,x:longint;
        y:rec;
begin
   i:=ll; j:=rr; x:=l[(ll+rr)>>1].len;
   while i<=j do
   begin
      while l[i].len>x do inc(i);
      while l[j].len<x do dec(j);
      if i<=j then
      begin
         y:=l[i]; l[i]:=l[j]; l[j]:=y;
         inc(i); dec(j);
      end;
   end;
   if i<rr then sort(i,rr);
   if j>ll then sort(ll,j);
end;

begin
   read(n);
   for i:=1 to n do father[i]:=i;
   for i:=1 to n do read(a[i]);
   tot:=0;
   for i:=1 to n do
     for j:=i+1 to n do
     begin
        inc(tot);
        l[tot].x:=i; l[tot].y:=j; l[tot].len:=a[i] xor a[j];
     end;
   sort(1,tot);
   tt:=0; ans:=0;
   for i:=1 to tot do
   begin
      tx:=get_father(l[i].x);
      ty:=get_father(l[i].y);
      if tx<>ty then
      begin
         inc(tt);
         father[tx]:=ty;
         inc(ans,int64(l[i].len));
         if tt=n-1 then break;
      end;
   end;
   writeln(ans);
end.
——by Eirlys



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值