题目描述
超牛{ superbull.pas/c/cpp}
农场有N (1 <= N <= 2000)头牛参加“超级牛声”比赛,每头牛有一个唯一的编号,范围是1...2^30-1。比赛采用1对1的淘汰赛,在一场比赛中,FJ有权决定淘汰其中的一头牛,并将两头牛的编号的XOR值作为本场比赛的得分。请帮助FJ设计比赛过程,使得整个赛事最后的总分值最大。
输入
第一行一个整数N。
接下来N行,每行一个整数,表示每头牛的编号。
输出
一行一个整数,表示赛事的最大总分值。
不难想到这题用最大生成树来写。
首先构造一个完全图,编号为x1的点(牛)到编号为x2的点的边权为 x1 xor x2。
显然最终的图是一棵树。
因为要求的是最大值,那么就是求最大生成树。
var i,j,n,tot:longint; ans:int64; num:array[0..2006] of int64; father:array[0..2006] of longint; u,v:array[0..4000000] of longint; cost:array[0..4000000] of int64; function getfather(k:longint):longint; begin if father[k]=k then exit(k); father[k]:=getfather(father[k]); getfather:=father[k]; end; procedure kruskal; var i,t1,t2:longint; begin for i:=1 to tot do begin t1:=getfather(u[i]); t2:=getfather(v[i]); if t1<>t2 then begin father[t1]:=t2; ans:=ans+cost[i]; end; end; end; procedure qsort(a,b:longint); var i,j,x,temp:longint; begin i:=a; j:=b; x:=cost[(i+j) div 2]; repeat while cost[i]>x do inc(i); while cost[j]<x do dec(j); if i<=j then begin temp:=u[i]; u[i]:=u[j]; u[j]:=temp; temp:=v[i]; v[i]:=v[j]; v[j]:=temp; temp:=cost[i]; cost[i]:=cost[j]; cost[j]:=temp; inc(i); dec(j); end; until i>j; if i<b then qsort(i,b); if a<j then qsort(a,j); end; begin //assign(input,‘superbull.in‘); //assign(output,‘superbull.out‘); //reset(input); //rewrite(output); readln(n); for i:=1 to n do father[i]:=i; for i:=1 to n do readln(num[i]); for i:=1 to n do for j:=1 to n do if i<>j then begin inc(tot); u[tot]:=i; v[tot]:=j; cost[tot]:=num[i] xor num[j]; end; qsort(1,tot); ans:=0; kruskal; writeln(ans); //close(input); //close(output); end.
时间: 2024-11-02 04:35:59