BZOj-3943: [Usaco2015 Feb]SuperBull

[文章目录]

Description

一共有N支球队参加这场比赛,每支球队都有一个特有的取值在1-2^30-1之间的整数编号(即:所有球队编号各不相同)。“犇”锦标赛是一个淘汰赛制的比赛——每场比赛过后,FJ选择一支球队淘汰,淘汰了的球队将不能再参加比赛。锦标赛在只有一支球队留下的时候就结束了。FJ发现了一个神奇的规律:在任意一场比赛中,这场比赛的得分是参加比赛两队的编号的异或(Xor)值。例如:编号为12的队伍和编号为20的队伍之间的比赛的得分是24分,因为 12(01100) Xor 20(10100) = 24(11000)。FJ相信比赛的得分越高,比赛就越好看,因此,他希望安排一个比赛顺序,使得所有比赛的得分和最高。请帮助FJ决定比赛的顺序。1<=N<=2000

我居然还在想什么拆位,什么高斯消元。。。
发现每两个队比赛的得分是亦或值,并且有n-1次比赛。如果这是一张图的话就是求一个完全图的最大生成树。
完全图的话还是邻接矩阵+prim比较好 复杂度O(n^2)

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
ll sum;
int n,w[2017];
int map[2017][2017];
bool v[2017];
void prim()
{
    memset(w,0xef,sizeof w); w[1]=0;
    int tmp,k;
    for(int i=1;i<n;++i)
    {
        tmp=0xefefefef;
        for(int j=1;j<=n;++j)
            if(!v[j]&&w[j]>tmp) tmp=w[j],k=j;
        v[k]=1;
        for(int j=1;j<=n;++j)
            if(!v[j]) w[j]=max(w[j],map[k][j]);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",w+i);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            map[i][j]=w[i]^w[j];
    prim();
    for(int i=1;i<=n;++i) sum+=w[i];
    printf("%lld",sum);
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注