洛谷 P4826 [USACO15FEB]Superbull S 图论 最小生成树

Posted 饮水思源的美西螈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P4826 [USACO15FEB]Superbull S 图论 最小生成树相关的知识,希望对你有一定的参考价值。

又是鸽了三千万年...

 

 --------------------------------------------------------------------

题目描述

Bessie and her friends are playing hoofball in the annual Superbull championship, and Farmer John is in charge of making the tournament as exciting as possible. A total of N (1<=<=2000)(1<=N<=2000) teams are playing in the Superbull. Each team is assigned a distinct integer team ID in the range 1...2^30-1 to distinguish it from the other teams. The Superbull is an elimination tournament -- after every game, Farmer John chooses which team to eliminate from the Superbull, and the eliminated team can no longer play in any more games. The Superbull ends when only one team remains.

Farmer John notices a very unusual property about the scores in matches! In any game, the combined score of the two teams always ends up being the bitwise exclusive OR (XOR) of the two team IDs. For example, if teams 12 and 20 were to play, then 24 points would be scored in that game, since 01100 XOR 10100 = 11000.

Farmer John believes that the more points are scored in a game, the more exciting the game is. Because of this, he wants to choose a series of games to be played such that the total number of points scored in the Superbull is maximized. Please help Farmer John organize the matches.

 

 

 

输入格式

The first line contains the single integer N. The following N lines contain the N team IDs.

输出格式

Output the maximum possible number of points that can be scored in the Superbull.

题意翻译

Bessie和她的朋友们正在一年一度的Superbull锦标赛中打球,而Farmer John负责让比赛尽可能激动人心。总共有 N 支队伍( 1≤N≤2000 )参加了Superbull锦标赛。每个团队都有一个 1...230−11...230−1的团队ID。

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

FJ注意到一个不寻常的事情:在任何游戏中,两个团队的总分是两个团队ID的按位异或(XOR)。例如,如果第 12 队和第 20 队将参加比赛,则该游戏的得分为 24 分,因为01100 XOR 10100 = 11000。

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

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

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

样例解释:让 3 队与 9 队进行比赛,并让 9 队晋级。然后他让 6 队和 9 队对决,让 6 队获胜。最后,第 6 队和第 10 队比赛, 10队获胜。总得分为:3 XOR 9+6 XOR 9+6 XOR 10=10+15+12=37。

输入输出样例
输入 #1
4
3
6
9
10
输出 #1
37

 

这题说实话,抽象起来是比较难的,但后期做起来就还可以了

一.抽象

找出题目的特点
 

1.淘汰赛:意味着n支队伍只有n-1次比赛,每个队伍只有一个队伍战胜自己

2.最大精彩值:所有比赛的情况都是最佳的

结合上面两点,就可以抽象出最小生成树,只不过排序顺序变一下

点:每支队伍

边:每支队伍之间的比赛

权值:比赛总比分

# include <iostream>
# include <cstdio>
# include <algorithm>
using namespace std;
# define int long long
int n,m,sum;
int id[2005];
int f[2005];
void make()
	for (int i=1;i<=n;i++)
		f[i]=i;
	

int find(int x)
	if (f[x]!=x)
		return f[x]=find(f[x]);
	
	return f[x];

struct node
	int u,v,w;
e[2005*2005];
void add(int u,int v,int w)
	m++;
	e[m].u=u;
	e[m].v=v;
	e[m].w=w;

bool cmp(node x,node y)
	return x.w>y.w;

void kruskal()
	make();
	int cnt=0;
	sort(e+1,e+1+m,cmp);
	for (int i=1;i<=m;i++)
		int a=find(e[i].u),b=find(e[i].v);
		if (a==b)
			continue;
		
		f[b]=a;
		cnt++;
		sum+=e[i].w;
		if (cnt==n-1)
		    return ;
		
	

signed main()
	scanf("%lld",&n);
	for (int i=1;i<=n;i++)
		scanf("%lld",&id[i]);
	
	for (int i=1;i<=n;i++)
		for (int j=i+1;j<=n;j++)
			add(i,j,id[i]^id[j]);
		
	
	kruskal();
	printf("%lld",sum);
	return 0;

SPFA cojs 176. [USACO Feb07] 奶牛聚会

cojs 176. [USACO Feb07] 奶牛聚会

★☆   输入文件:sparty.in   输出文件:sparty.out   简单对比
时间限制:3 s   内存限制:16 MB

 

N(1 ≤ N ≤ 1000)个农场中的每个农场都有一只奶牛去参加位于第X个农场的聚会.共有M (1 ≤ M ≤ 100,000)条单向的道路,每条道路连接一对农场.通过道路i会花费Ti (1 ≤ Ti ≤ 100)的时间.

作为参加聚会的奶牛必须走到聚会的所在地(农场X).当聚会结束时,还要返回各自的农场.奶牛都是很懒的,她们想找出花费时间最少的路线.由于道路都是单向的,所有她们前往农场X的路线可能会不同于返程的路线.

Of all the cows, what is the longest amount of time a cow must spend walking to the party and back? 对于所有参加聚会的奶牛,找出前往聚会和返程花费总时间最多的奶牛,输出这只奶牛花费的总时间.


输入格式:

  • 第1行:三个用空格隔开的整数.

第2行到第M+1行,每行三个用空格隔开的整数:Ai, Bi,以及Ti.表示一条道路的起点,终点和需要花费的时间.


输出格式:

  • 唯一一行:一个整数: 所有参加聚会的奶牛中,需要花费总时间的最大值.

样例输出:

4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3

样例输入:

10

样例说明:

共有4只奶牛参加聚会,有8条路,聚会位于第2个农场.

第4只奶牛可以直接到聚会所在地(花费3时间),然后返程路线经过第1和第3个农场(花费7时间),总共10时间.

  1 #define N 100100
  2 #include<cstring>
  3 #include<iostream>
  4 using namespace std;
  5 #include<cstdio>
  6 int que[10000];
  7 int head1[1001],head2[1001];
  8 struct Edge{
  9     int v,last,w;
 10 }edge1[N],edge2[N];
 11 int t1=0,t2=0,n,m,x;
 12 int dis1[1001],dis2[1001],ans=0;
 13 void add_edge1(int u,int v,int w)
 14 {
 15     ++t1;
 16     edge1[t1].v=v;
 17     edge1[t1].w=w;
 18     edge1[t1].last=head1[u];
 19     head1[u]=t1;
 20 }
 21 void add_edge2(int u,int v,int w)
 22 {
 23     ++t2;
 24     edge2[t2].v=v;
 25     edge2[t2].w=w;
 26     edge2[t2].last=head2[u];
 27     head2[u]=t2;
 28 }
 29 void input()
 30 {
 31     scanf("%d%d%d",&n,&m,&x);
 32     for(int i=1;i<=m;++i)
 33     {
 34         int u,v,w;
 35         scanf("%d%d%d",&u,&v,&w);
 36         add_edge1(u,v,w);
 37         add_edge2(v,u,w);
 38     }
 39 }
 40 void SPFA1()
 41 {
 42     bool flag[1001]={0};
 43     memset(flag,false,sizeof(flag));
 44     int head=0,tail=0;
 45     que[++tail]=x;
 46     flag[x]=true;
 47     memset(dis1,99,sizeof(dis1));
 48     dis1[x]=0;
 49     while(head<tail)
 50     {
 51         ++head;
 52         int p=que[head];
 53         flag[p]=false;
 54         for(int l=head1[p];l;l=edge1[l].last)
 55         {
 56             if(dis1[edge1[l].v]>dis1[p]+edge1[l].w)
 57             {
 58                 dis1[edge1[l].v]=dis1[p]+edge1[l].w;
 59                 if(!flag[edge1[l].v])
 60                 {
 61                     ++tail;
 62                     que[tail]=edge1[l].v;
 63                     flag[edge1[l].v]=true;
 64                 }
 65                 
 66             }
 67         }
 68         
 69     }
 70 }
 71 void SPFA2()
 72 {
 73     bool flag[1001]={0};
 74     memset(flag,false,sizeof(flag));
 75     int head=0,tail=0;
 76     memset(que,0,sizeof(que));
 77     que[++tail]=x;
 78     flag[x]=true;
 79     memset(dis2,99,sizeof(dis2));
 80     dis2[x]=0;
 81     while(head<tail)
 82     {
 83         ++head;
 84         int p=que[head];
 85         flag[p]=false;
 86         for(int l=head2[p];l;l=edge2[l].last)
 87         {
 88             if(dis2[edge2[l].v]>dis2[p]+edge2[l].w)
 89             {
 90                 dis2[edge2[l].v]=dis2[p]+edge2[l].w;
 91                 if(!flag[edge2[l].v])
 92                 {
 93                     ++tail;
 94                     que[tail]=edge2[l].v;
 95                     flag[edge2[l].v]=true;
 96                 }
 97                 
 98             }
 99         }
100         
101     }
102 }
103 int main()
104 {
105     freopen("sparty.in","r",stdin);
106     freopen("sparty.out","w",stdout);
107     input();
108     SPFA1();
109     SPFA2();
110     for(int i=1;i<=n;++i)
111       ans=max(ans,dis1[i]+dis2[i]);
112     printf("%d\n",ans);
113     fclose(stdin);fclose(stdout);
114     return 0;
115 }

 

以上是关于洛谷 P4826 [USACO15FEB]Superbull S 图论 最小生成树的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P3121 [USACO15FEB]审查(黄金)Censoring (Gold) AC自动机+栈

「题解」USACO15FEB Fencing the Herd G

洛谷P3045 [USACO12FEB]牛券Cow Coupons

洛谷P3048 [USACO12FEB]牛的IDCow IDs

洛谷P1607 [USACO09FEB]庙会班车Fair Shuttle

洛谷P2896 [USACO08FEB]一起吃饭Eating Together