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.结构体里面删掉一些东西会快?

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

  1 #pragma GCC optimize("Ofast")
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 #include<cassert>
  7 using namespace std;
  8 #define fi first
  9 #define se second
 10 #define mp make_pair
 11 #define pb push_back
 12 typedef long long ll;
 13 typedef unsigned long long ull;
 14 struct pii
 15 {
 16     int fi,se;
 17     pii():fi(0),se(0){}
 18     pii(int a,int b):fi(a),se(b){}
 19 };
 20 struct P
 21 {
 22     int a,b,c;
 23 };
 24 namespace S
 25 {
 26 
 27 const int N=7000000;
 28 struct N
 29 {
 30     int ch[2],fi,se;//,sz
 31 }dd[N];
 32 int mem;
 33 int rt;
 34 int gnode()
 35 {
 36     int t=++mem;dd[t].ch[0]=dd[t].ch[1]=0;//dd[t].sz=0;
 37     dd[t].fi=dd[t].se=0;
 38     return t;
 39 }
 40 const int dep=30;
 41 #define num rt
 42 void insert(int x,int y)
 43 {
 44     //if(!num)    num=gnode();
 45     //++dd[num].sz;
 46     int d;int i,p=num;
 47     /*
 48     if(!(dd[p].fi==y||dd[p].se==y))
 49     {
 50         if(!dd[p].fi)    dd[p].fi=y;
 51         else if(!dd[p].se)    dd[p].se=y;
 52     }
 53     */
 54     for(i=dep;i>=0;--i)
 55     {
 56         d=(x>>i)&1;
 57         if(!dd[p].ch[d])   dd[p].ch[d]=gnode();
 58         p=dd[p].ch[d];//++dd[p].sz;
 59         if(!(dd[p].fi==y||dd[p].se==y))
 60         {
 61             (dd[p].fi?dd[p].se:dd[p].fi)=y;
 62             /*
 63             if(!dd[p].fi)    dd[p].fi=y;
 64             else if(!dd[p].se)    dd[p].se=y;
 65             */
 66         }
 67     }
 68 }
 69 /*
 70 void erase(int x)
 71 {
 72     --dd[num].sz;
 73     bool d;int i,p=num;
 74     for(i=dep;i>=0;--i)
 75     {
 76         d=x&(1<<i);
 77         p=dd[p].ch[d];
 78         assert(p);
 79         --dd[p].sz;
 80     }
 81 }
 82 */
 83 //inline bool jud(int p,int y)
 84 //{
 85 //    return 
 86 #define jud(p,y)    (!dd[p].fi||(dd[p].fi==y&&!dd[p].se))
 87 //}
 88 pii que(int x,int y)
 89 {
 90     int p=num;
 91     int d,d2;int i,an=0;
 92     for(i=dep;i>=0;--i)
 93     {
 94         d=(x>>i)&1;
 95         //d=(x&(1<<i));
 96         d2=jud(dd[p].ch[d],y);
 97         p=dd[p].ch[d^d2];
 98         (an|=(d2*(1<<i)));
 99     }
100     if(dd[p].fi!=y)    return pii(an,dd[p].fi);
101     else    return pii(an,dd[p].se);
102 }
103 #undef num
104 
105 }
106 int n,a[200010],fa[200010];
107 //vector<int> d[200010];
108 P tmp[200010];int tlen;
109 ll ans;
110 int n1;
111 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
112 inline void merge(int x,int y,int z)
113 {
114     //printf("1t%d %d %d\n",x,y,z);
115     x=find(x);y=find(y);
116     //scanf("%d",new int);
117     if(x==y)    return;
118     fa[x]=y;ans+=z;--n1;
119 }
120 struct E
121 {
122     int to,nxt;
123 }e[200010];
124 int f1[200010],ne;
125 int main()
126 {
127     int i,k,fx;pii an,t;
128     //n=200000;
129     scanf("%d",&n);
130     for(i=1;i<=n;++i)
131     {
132         //a[i]=rand()%(1<<30);
133         scanf("%d",&a[i]);
134     }
135     for(i=1;i<=n;++i)
136         fa[i]=i;
137     n1=n;
138     //for(int ttt=1;ttt<=15;++ttt)//
139     while(n1>1)
140     {
141         //printf("1t%d\n",n1);
142         S::mem=0;S::rt=S::gnode();
143         tlen=0;
144         memset(f1+1,0,sizeof(f1[0])*n);
145         ne=0;
146         for(i=1;i<=n;++i)
147         {
148             fx=find(i);
149             S::insert(a[i],fx);
150             e[++ne].to=i;e[ne].nxt=f1[fx];f1[fx]=ne;
151             //d[find(i)].pb(i);
152         }
153         for(i=1;i<=n;++i)
154             if(find(i)==i)
155             {
156                 //for(k=f1[i];k;k=e[k].nxt)
157                 //    S::erase(a[e[k].to]);
158                 an=pii(0x3f3f3f3f,0x3f3f3f3f);
159                 for(k=f1[i];k;k=e[k].nxt)
160                 {
161                     t=S::que(a[e[k].to],i);
162                     if(t.fi<an.fi)    an=t;
163                 }
164                 //printf("at%d %d %d\n",i,an.fi,an.se);
165                 tmp[++tlen].a=i;tmp[tlen].b=an.se;tmp[tlen].c=an.fi;
166                 //merge(i,an.se,an.fi);
167                 //for(k=f1[i];k;k=e[k].nxt)
168                 //    S::insert(a[e[k].to],i);
169             }
170         for(i=1;i<=tlen;++i)
171             merge(tmp[i].a,tmp[i].b,tmp[i].c);
172         //puts("end");
173     }
174     printf("%lld",ans);
175     return 0;
176 }
View Code

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

 

posted @ 2018-10-31 10:24  hehe_54321  阅读(359)  评论(0编辑  收藏  举报
AmazingCounters.com