https://codeforces.com/contest/888/problem/G

这题可以用Boruvka算法:

一开始每个点是一个连通块。每次迭代对于每个连通块找到其最近邻居(与其有边相连且与其间最短边最短的连通块),然后将每个连通块和其最近邻居合并(选择的边自然是两连通块间最短边)。直到只剩一个连通块。考虑每一次迭代,连通块个数至少减半,因此只会进行O(log n)次迭代。边权有相等时可能需要一些特判

摘自wikipedia

Cut property

For any cut C of the graph, if the weight of an edge e in the cut-set of C is strictly smaller than the weights of all other edges of the cut-set of C, then this edge belongs to all MSTs of the graph.

Proof: Assume that there is an MST T that does not contain e. Adding e to T will produce a cycle, that crosses the cut once at e and crosses back at another edge e' . Deleting e' we get a spanning tree T∖{e'}∪{e} of strictly smaller weight than T. This contradicts the assumption that T was a MST.

By a similar argument, if more than one edge is of minimum weight across a cut, then each such edge is contained in some minimum spanning tree.

This figure shows the cut property of MSTs. T is the only MST of the given graph. If S = {A,B,D,E}, thus V-S = {C,F}, then there are 3 possibilities of the edge across the cut(S,V-S), they are edges BC, EC, EF of the original graph. Then, e is one of the minimum-weight-edge for the cut, therefore S ∪ {e} is part of the MST T.

对于此题,只要把这个算法的每一次迭代用01trie优化即可(不展开写了);对于边权相等,用并查集维护连通性,在已经连通时不合并即可

然而此题卡常(理论复杂度O(200000*log2(200000)*30啊,怎么只开2s)。。。按官方题解里面一模一样的算法A不掉。。

对于此题某一版本的代码(默认随机种子跑200000):结构体+数组(5500ms) 快于 直接数组(5800ms)  快于  结构体+指针(7000ms);不知道原因

卡常:

1.(d?(1<<i):0),(d<<i),d*(1<<i)中,最后一个最快?

2.结构体里面删掉一些东西会快?

卡了几个小时卡过去了。。。

 #pragma GCC optimize("Ofast")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cassert>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
struct pii
{
int fi,se;
pii():fi(),se(){}
pii(int a,int b):fi(a),se(b){}
};
struct P
{
int a,b,c;
};
namespace S
{ const int N=;
struct N
{
int ch[],fi,se;//,sz
}dd[N];
int mem;
int rt;
int gnode()
{
int t=++mem;dd[t].ch[]=dd[t].ch[]=;//dd[t].sz=0;
dd[t].fi=dd[t].se=;
return t;
}
const int dep=;
#define num rt
void insert(int x,int y)
{
//if(!num) num=gnode();
//++dd[num].sz;
int d;int i,p=num;
/*
if(!(dd[p].fi==y||dd[p].se==y))
{
if(!dd[p].fi) dd[p].fi=y;
else if(!dd[p].se) dd[p].se=y;
}
*/
for(i=dep;i>=;--i)
{
d=(x>>i)&;
if(!dd[p].ch[d]) dd[p].ch[d]=gnode();
p=dd[p].ch[d];//++dd[p].sz;
if(!(dd[p].fi==y||dd[p].se==y))
{
(dd[p].fi?dd[p].se:dd[p].fi)=y;
/*
if(!dd[p].fi) dd[p].fi=y;
else if(!dd[p].se) dd[p].se=y;
*/
}
}
}
/*
void erase(int x)
{
--dd[num].sz;
bool d;int i,p=num;
for(i=dep;i>=0;--i)
{
d=x&(1<<i);
p=dd[p].ch[d];
assert(p);
--dd[p].sz;
}
}
*/
//inline bool jud(int p,int y)
//{
// return
#define jud(p,y) (!dd[p].fi||(dd[p].fi==y&&!dd[p].se))
//}
pii que(int x,int y)
{
int p=num;
int d,d2;int i,an=;
for(i=dep;i>=;--i)
{
d=(x>>i)&;
//d=(x&(1<<i));
d2=jud(dd[p].ch[d],y);
p=dd[p].ch[d^d2];
(an|=(d2*(<<i)));
}
if(dd[p].fi!=y) return pii(an,dd[p].fi);
else return pii(an,dd[p].se);
}
#undef num }
int n,a[],fa[];
//vector<int> d[200010];
P tmp[];int tlen;
ll ans;
int n1;
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
inline void merge(int x,int y,int z)
{
//printf("1t%d %d %d\n",x,y,z);
x=find(x);y=find(y);
//scanf("%d",new int);
if(x==y) return;
fa[x]=y;ans+=z;--n1;
}
struct E
{
int to,nxt;
}e[];
int f1[],ne;
int main()
{
int i,k,fx;pii an,t;
//n=200000;
scanf("%d",&n);
for(i=;i<=n;++i)
{
//a[i]=rand()%(1<<30);
scanf("%d",&a[i]);
}
for(i=;i<=n;++i)
fa[i]=i;
n1=n;
//for(int ttt=1;ttt<=15;++ttt)//
while(n1>)
{
//printf("1t%d\n",n1);
S::mem=;S::rt=S::gnode();
tlen=;
memset(f1+,,sizeof(f1[])*n);
ne=;
for(i=;i<=n;++i)
{
fx=find(i);
S::insert(a[i],fx);
e[++ne].to=i;e[ne].nxt=f1[fx];f1[fx]=ne;
//d[find(i)].pb(i);
}
for(i=;i<=n;++i)
if(find(i)==i)
{
//for(k=f1[i];k;k=e[k].nxt)
// S::erase(a[e[k].to]);
an=pii(0x3f3f3f3f,0x3f3f3f3f);
for(k=f1[i];k;k=e[k].nxt)
{
t=S::que(a[e[k].to],i);
if(t.fi<an.fi) an=t;
}
//printf("at%d %d %d\n",i,an.fi,an.se);
tmp[++tlen].a=i;tmp[tlen].b=an.se;tmp[tlen].c=an.fi;
//merge(i,an.se,an.fi);
//for(k=f1[i];k;k=e[k].nxt)
// S::insert(a[e[k].to],i);
}
for(i=;i<=tlen;++i)
merge(tmp[i].a,tmp[i].b,tmp[i].c);
//puts("end");
}
printf("%lld",ans);
return ;
}

另外,官方题解下面有评论讲了一种其他做法,常数更小的

Xor-MST Codeforces - 888G的更多相关文章

  1. Codeforces.888G.Xor-MST(Borůvka算法求MST 贪心 Trie)

    题目链接 \(Description\) 有一张\(n\)个点的完全图,每个点的权值为\(a_i\),两个点之间的边权为\(a_i\ xor\ a_j\).求该图的最小生成树. \(n\leq2*10 ...

  2. Codeforces 888G Xor-MST - 分治 - 贪心 - Trie

    题目传送门 这是一条通往vjudge的高速公路 这是一条通往Codeforces的高速公路 题目大意 给定一个$n$阶完全图,每个点有一个权值$a_{i}$,边$(i, j)$的权值是$(a_{i}\ ...

  3. codeforces 888G Xor-MST

    You are given a complete undirected graph with n vertices. A number ai is assigned to each vertex, a ...

  4. Codeforces 888G(分治+trie)

    按位贪心,以当前考虑位是0还是1将数分成两部分,则MST中这两部分之间只会存在一条边,因为一旦有两条或以上的边,考虑两条边在原图中所成的环,显然这两条边有一条是环上的权值最大边,不会出现在MST中.则 ...

  5. Maximum Xor Secondary CodeForces - 281D (单调栈)

    Bike loves looking for the second maximum element in the sequence. The second maximum element in the ...

  6. Xor-MST CodeForces - 888G (最小生成树,分治)

    大意: n结点无向完全图, 给定每个点的点权, 边权为两端点异或值, 求最小生成树

  7. 2018.9.25 NOIP模拟赛

    *注意:这套题目应版权方要求,不得公示题面. 从这里开始 Problem A XOR Problem B GCD Problem C SEG 表示十分怀疑出题人水平,C题数据和标程都是错的.有原题,差 ...

  8. codeforces 22E XOR on Segment 线段树

    题目链接: http://codeforces.com/problemset/problem/242/E E. XOR on Segment time limit per test 4 seconds ...

  9. Codeforces 627 A. XOR Equation (数学)

    题目链接:http://codeforces.com/problemset/problem/627/A 题意: 告诉你s 和 x,a + b = s    a xor b = x   a, b > ...

随机推荐

  1. IOS从背景图中取色

    ​1. [代码][其他]代码     void *bitmapData; //内存空间的指针,该内存空间的大小等于图像使用RGB通道所占用的字节数. static CGContextRef Creat ...

  2. jsp报An error has occurred. See error log for more details. Argument not valid错误

    An error has occurred. See error log for more details. Argument not valid 翻译过来是:一个错误已经发生.看到更多的细节错误日志 ...

  3. 常规问题解决:File "/usr/bin/yum", line 30 及 File "/usr/libexec/urlgrabber-ext-down", line 28

    在执行yum命令时忽然发现出现以下报错: # yum list File "/usr/bin/yum", line 30 except KeyboardInterrupt, e: ...

  4. python sorted函数的小练习

    前两天学习了一下socket编程,在向某大神请教问题时被嫌弃了,有一种还没学会走就想跑的感觉.大神说我现在的水平应该去做一些像是操作文件.序列号等的小练习来加深理解.下面是他给我出的小练习: 1.da ...

  5. java中的异常The given object has a null identifier

    修改页面点击提交时报如下异常: org.hibernate.TransientObjectException: The given object has a null identifier: com. ...

  6. 洛谷P1522牛的旅行——floyd

    题目:https://www.luogu.org/problemnew/show/P1522 懒于仔细分情况而直接像题解那样写floyd然后不明白最后一步max的含义了... 分开考虑怎么保证在一个内 ...

  7. tyvj1940创世纪——贪心(基环树)

    题目:http://www.joyoi.cn/problem/tyvj-1940 基环树的样子,看了书上的讲解,准备写树上DP,然后挂了: #include<iostream> #incl ...

  8. 怎样编写高质量的 Java 代码

    代码质量概述 怎样辨别一个项目代码写得好还是坏?优秀的代码和腐化的代码区别在哪里?怎么让自己写的代码既漂亮又有生命力?接下来将对代码质量的问题进行一些粗略的介绍.也请有过代码质量相关经验的朋友提出宝贵 ...

  9. 抓屏工具 faststone capture

    百度百科 http://baike.baidu.com/link?url=te51CfOKYIEmqT1jsyRwcB8Pnals5xQ8nUXk6trvBPGSJRBO5G7BEZL7cYQxmx8 ...

  10. Laravel之简单的学生信息管理平台

    laravel框架写的简易版的学生信息管理平台,贯穿了laravel的控制器.视图.模板.模型.中间件.路由规则的使用. 页面是使用BootStrap前端框架搭建 使用laravel实现了增删改查的功 ...