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 > ...
随机推荐
- html5--3.10 input元素(9)
html5--3.10 input元素(9) 学习要点 input元素及其属性 input元素 用来设置表单中的内容项,比如输入内容的文本框,按钮等 不仅可以布置在表单中,也可以在表单之外的元素使用 ...
- python string写入二进制文件——直接wb形式open file,再write string即可
4 down vote accepted You misunderstood what \xhh does in Python strings. Using \x notation in Python ...
- jquery data 选择器 表格序列化serialize()
data()在元素上存放或者读取数据,返回jquery对象. demo: <div data-obj="{'name':'zhangsan','age':20}">&l ...
- 7、html的body内标签之图片及表格
一.image <a href="https://www.baidu.com" target="_blank"> <img src=" ...
- python之继承、抽象类、派生、多态、组合、封装
1.继承概念的实现方式主要有2类:实现继承.接口继承. Ø 实现继承是指使用基类的属性和方法而无需额外编码的能力: Ø 接口继承是指仅使用属性和方法的名称.子类必须提供 ...
- 转载 关于启用HTTPS的一些经验分享
本文转载自 https://imququ.com/post/sth-about-switch-to-https.html 随着国内网络环境的持续恶化,各种篡改和劫持层出不穷,越来越多的网站选择了全站 ...
- 验证网站SiteMap的工具
验证网站SiteMap的在线工具 http://www.xmlvalidation.com/ 在SiteMap文件中,不能直接这样写url "http://www.obriensplast ...
- java的Set, List, Map简单介绍
Set, List, Map Set和List,Map都是集合,Set和List都是继承于Collection接口,而Map不是. 1.Map(映射) :Map是以key,Value的形式存储数据的映 ...
- myeclipse 2014 没有Install New Software的解决办法
要安装离线zip包,但在myeclipse2014的help菜单中找不到 Install New Software 解决如下: help--install from site--add--archiv ...
- c#静态多态性与动态多态性
C# 多态性 多态性意味着有多重形式.在面向对象编程范式中,多态性往往表现为"一个接口,多个功能". 多态性可以是静态的或动态的.在静态多态性中,函数的响应是在编译时发生的.在动态 ...