bzoj 3943 最大生成树

来源:互联网 发布:js只能输入0到100 编辑:程序博客网 时间:2024/05/18 15:54

题意:给定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