zoukankan      html  css  js  c++  java
  • [USACO15FEB]Superbull 超级牛

    题意概况

    题目描述

    (Bessie)和她的朋友们正在一年一度的(Superbull)锦标赛中打球,而(Farmer John)负责让比赛尽可能激动人心。

    总共有 (N) 支队伍 (1 le N le 2000) 参加了(Superbull)锦标赛。每个团队都有一个 (1 dots 2^{30}-1)的团队ID。

    (Superbull)是一场淘汰赛 - 在每场比赛之后,(FJ)选择淘汰其中一支球队,而被淘汰的球队再也无法参加任何比赛了。当只剩下一支球队时,比赛就结束了。

    (FJ)注意到一个不寻常的事情:在任何游戏中,两个团队的总分是两个团队ID的按位异或(XOR)。

    例如,如果第 (12) 队和第 (20) 队将参加比赛,则该游戏的得分为 (24) 分,因为({01100} quad xor quad {10100} = {11000})

    FJ想要设计一种比赛方案,让所有比赛的得分总和最大。请帮助(Farmer John)组织比赛。

    输入输出格式

    输入格式:第一行包括一个整数 (N) ,下面 (N) 行每行包括一个队伍的ID。

    输出格式:输出一个整数,代表比赛的最大总得分。

    样例解释

    (3) 队与 (9) 队进行比赛,并让 (9) 队晋级。

    然后他让 (6) 队和 (9) 队对决,让(6)队获胜。

    最后,第 (6) 队和第 (10) 队比赛,(10)队获胜。

    总得分为:(3 quad xor quad 9+6 quad xor quad 9+6 quad xor quad 10=10+15+12=37。)

    样例输入

    4
    3
    6
    9
    10
    

    样例输出

    37
    

    数据范围

    (1 le N le 2000)

    解题报告

    题意理解

    1. 给定(n)个人,比(n-1)场比赛

    2. 对于一场比赛的精彩度是两个比赛队伍的编号异或

    3. 要求所有的比赛的精彩度之和最大.

    算法解析

    首先,这道题目难在建图上面.

    我们可以分析一下,这道题目的比赛模式.

    这就是一场竞赛的四场比赛的形式.

    我们发现

    1. 一共比了(n-1)场比赛,有(n)个人,呈现,树形结构
    2. 对于一场比赛,谁赢谁输并没有什么影响.
    3. 我们要求这些边权最大,且只能有(n-1)条边
    4. 一条边的边权,是两点编号的异或.

    综上所述,我们可以使用最小生成树的变形,最大生成树来求解本题.


    代码解析

    #include <bits/stdc++.h>
    using namespace std;
    const int N=2010;
    int a[N],n,m,cnt,fa[N];
    struct node
    {
    	int x,y,w;
    } g[N*N];
    int cmp(node a,node b)//最大排序
    {
    	return a.w>b.w;
    }
    inline int find(int x)
    {
    	return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    inline void kruskal()
    {
    	for(int i=1; i<=n; i++)//建立图
    		for(int j=1; j<=n; j++)
    			if (i!=j)
    				g[++cnt]= {i,j,a[i]^a[j]};//边权为异或
    	sort(g+1,g+1+cnt,cmp);//kruskal排序
    	int cc=0;
    	long long ans=0ll;//记得开long long
    	for(int i=1; i<=cnt; i++)
    	{
    		int x=find(g[i].x),y=find(g[i].y);
    		if (x==y)//已经联合
    			continue;
    		fa[x]=y;
    		ans+=g[i].w;
    		if (cc==n-1)//n-1条边凑齐了
    			break;
    	}
    	printf("%lld
    ",ans);
    }
    inline void init()
    {
    	scanf("%d",&n);
    	for(int i=1; i<=n; i++)
    		scanf("%d",&a[i]),fa[i]=i;
    	kruskal();
    }
    signed main()
    {
    	init();
    	return 0;
    }
    
  • 相关阅读:
    在vue项目中引用element-ui时 让el-input 获取焦点的方法
    vue cli 平稳升级webapck4
    如何在 vuex action 中获取到 vue 实例
    Vue主要原理最简实现与逻辑梳理
    vue自定义指令clickoutside扩展--多个元素的并集作为inside
    关于使用element中的popup问题
    教你如何检查一个函数是否为JavaScript运行时环境内建函数
    用 Vue 做一个简单的购物app
    vue 手机键盘把底部按钮顶上去
    基于Linux的智能家居的设计(2)
  • 原文地址:https://www.cnblogs.com/gzh-red/p/11822785.html
Copyright © 2011-2022 走看看