USACO superbull(MST)

来源:互联网 发布:javascript 资源 网盘 编辑:程序博客网 时间:2024/05/01 22:25

题意:n支队伍,每支队伍权值a[i],队伍i和队伍j打比赛会产生a[i] xor a[j]这么多精彩度,但每举行一场比赛你必须淘汰其中一支队伍,淘汰的队伍不能再参赛,请你安排一系列比赛使得最后能够产生冠军,并且使得精彩度最大。n<=2000。

容易发现最多打(n-1)场比赛。我考试时乱做的,就把所有边排序选前n-1条。

其实n-1条边连接了n个点,很明显是一棵树,所以跑一下最大生成树就行了。由于是完全图,所以产生的边会很对,用prim比kruskal更优。


然后实现的时候我用的自创的用来优化dijkstra的数据结构,可以把空间复杂度严格限制在O(n),在完全图中效果特别明显,用堆的都是几十MB,我1MB,并且快很多。


#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define LL long longconst int MAXN = 2005;int a[MAXN], N;int dis[MAXN], maxp[MAXN*2];bool used[MAXN];inline void pushup(int&p) {int &r = maxp[p];r = p * !used[p];if (dis[maxp[p<<1]] > dis[r]) r = maxp[p<<1];if (dis[maxp[p<<1|1]] > dis[r]) r = maxp[p<<1|1];}void relax(int p, int d) {if (d < dis[p]) return;dis[p] = d;for (int i = p; i; i>>=1) pushup(i);}void finish(int p) {used[p] = 1;for (int i = p; i; i>>=1) pushup(i);}LL Prim() {relax(1, 0);LL res = 0;for (int i = 1; i<=N; ++i){int u = maxp[1];res += dis[u];finish(u);for (int j = 1; j<=N; ++j)if (j != u && !used[j]) relax(j, a[j]^a[u]);}return res;}int main(){cin >> N;for (int i = 1; i<=N; ++i) cin >> a[i];cout << Prim() << '\n';return 0;}


1 0
原创粉丝点击