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 > ...
随机推荐
- Spring Boot2.0之 整合Zookeeper集群
普通的连接: pom: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://w ...
- zabbix数据库创建初始化
MariaDB [(none)]> create database zabbix character set utf8; MariaDB [(none)]> grant all privi ...
- 20171202作业1python入门
1.简述编译型与解释型语言的区别,且分别列出你知道的哪些语言属于编译型,哪些属于解释型 编译型:需要编译器,执行前一次性翻译成机器能读懂的代码(如c,c++,执行速度快,调试麻烦) 解释型:需要解释器 ...
- HihoCoder 1570 : 小Hi与法阵(简单几何)
描述 小Hi喜欢大,而小Ho喜欢小.他们所在的城市(视为二维平面)有N座法阵.现在他们各选三座法阵,以三座法阵为顶点组成三角形,并站在所选三角形的重心位置:二人选择的法阵可以有相同的.小Hi选择面积最 ...
- Java笔记(五)
泛型:JDK1.5版本后出现的新特性.用于解决安全问题,是一个类型安全机制. 好处:将运行期间出现问题ClassCastException,转移到了编译时期.方便程序员解决问题,让运行时问题减少. 避 ...
- CentOS7设置系统/yum以及firefox web代理上网
一.系统全局的代理设置: 用vi/vim编辑器打开/etc/profile,追加如下内容: http_proxy=http://192.168.78.124:8080 ftp_proxy=http:/ ...
- 关于ubuntu 16.04 docker常用命令
1.sudo docker ps -a 查看当前docker实例的信息: CONTAINER ID IMAGE COMMAND ...
- 阿里云CDNapi
#!/usr/bin/env python from aliyunsdkcore import client import json from aliyunsdkcdn.request.v201411 ...
- 《Linux内核修炼之道》精华分享与讨论(5)——Kernel地图:Kconfig与Makefile
转自:http://blog.csdn.net/fudan_abc/article/details/5340408 Makefile不是Make Love 从前在学校,混了四年,没有学到任何东西,每天 ...
- 【转】cache buffer chain 第一篇
文章转自:http://www.jydba.net/cache-buffer-chain/ buffer cache的管理有两个重要的数据结构: hash bucket和cache buffer ch ...