Xor-MST Codeforces - 888G
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的更多相关文章
- Codeforces.888G.Xor-MST(Borůvka算法求MST 贪心 Trie)
题目链接 \(Description\) 有一张\(n\)个点的完全图,每个点的权值为\(a_i\),两个点之间的边权为\(a_i\ xor\ a_j\).求该图的最小生成树. \(n\leq2*10 ...
- Codeforces 888G Xor-MST - 分治 - 贪心 - Trie
题目传送门 这是一条通往vjudge的高速公路 这是一条通往Codeforces的高速公路 题目大意 给定一个$n$阶完全图,每个点有一个权值$a_{i}$,边$(i, j)$的权值是$(a_{i}\ ...
- codeforces 888G Xor-MST
You are given a complete undirected graph with n vertices. A number ai is assigned to each vertex, a ...
- Codeforces 888G(分治+trie)
按位贪心,以当前考虑位是0还是1将数分成两部分,则MST中这两部分之间只会存在一条边,因为一旦有两条或以上的边,考虑两条边在原图中所成的环,显然这两条边有一条是环上的权值最大边,不会出现在MST中.则 ...
- Maximum Xor Secondary CodeForces - 281D (单调栈)
Bike loves looking for the second maximum element in the sequence. The second maximum element in the ...
- Xor-MST CodeForces - 888G (最小生成树,分治)
大意: n结点无向完全图, 给定每个点的点权, 边权为两端点异或值, 求最小生成树
- 2018.9.25 NOIP模拟赛
*注意:这套题目应版权方要求,不得公示题面. 从这里开始 Problem A XOR Problem B GCD Problem C SEG 表示十分怀疑出题人水平,C题数据和标程都是错的.有原题,差 ...
- codeforces 22E XOR on Segment 线段树
题目链接: http://codeforces.com/problemset/problem/242/E E. XOR on Segment time limit per test 4 seconds ...
- Codeforces 627 A. XOR Equation (数学)
题目链接:http://codeforces.com/problemset/problem/627/A 题意: 告诉你s 和 x,a + b = s a xor b = x a, b > ...
随机推荐
- IOS从背景图中取色
1. [代码][其他]代码 void *bitmapData; //内存空间的指针,该内存空间的大小等于图像使用RGB通道所占用的字节数. static CGContextRef Creat ...
- 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 翻译过来是:一个错误已经发生.看到更多的细节错误日志 ...
- 常规问题解决: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: ...
- python sorted函数的小练习
前两天学习了一下socket编程,在向某大神请教问题时被嫌弃了,有一种还没学会走就想跑的感觉.大神说我现在的水平应该去做一些像是操作文件.序列号等的小练习来加深理解.下面是他给我出的小练习: 1.da ...
- java中的异常The given object has a null identifier
修改页面点击提交时报如下异常: org.hibernate.TransientObjectException: The given object has a null identifier: com. ...
- 洛谷P1522牛的旅行——floyd
题目:https://www.luogu.org/problemnew/show/P1522 懒于仔细分情况而直接像题解那样写floyd然后不明白最后一步max的含义了... 分开考虑怎么保证在一个内 ...
- tyvj1940创世纪——贪心(基环树)
题目:http://www.joyoi.cn/problem/tyvj-1940 基环树的样子,看了书上的讲解,准备写树上DP,然后挂了: #include<iostream> #incl ...
- 怎样编写高质量的 Java 代码
代码质量概述 怎样辨别一个项目代码写得好还是坏?优秀的代码和腐化的代码区别在哪里?怎么让自己写的代码既漂亮又有生命力?接下来将对代码质量的问题进行一些粗略的介绍.也请有过代码质量相关经验的朋友提出宝贵 ...
- 抓屏工具 faststone capture
百度百科 http://baike.baidu.com/link?url=te51CfOKYIEmqT1jsyRwcB8Pnals5xQ8nUXk6trvBPGSJRBO5G7BEZL7cYQxmx8 ...
- Laravel之简单的学生信息管理平台
laravel框架写的简易版的学生信息管理平台,贯穿了laravel的控制器.视图.模板.模型.中间件.路由规则的使用. 页面是使用BootStrap前端框架搭建 使用laravel实现了增删改查的功 ...