zoukankan      html  css  js  c++  java
  • Xor-MST Codeforces

    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
    ",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
    ",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
    ",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

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

  • 相关阅读:
    软件工程课后作业3:如何返回一个整数数组中最大子数组的和
    软件工程课后作业2:四则运算题目扩展:可指定题目数量并且支持真分数运算
    软件工程课后作业1:三十道四则运算题目
    团队作业3返回整数数组中最大子数组的和(多个数组)
    求一个二维数组所有子数组和的最大值(郭少周,陈泽)
    郭少周和陈泽两人合作课堂练习和课下作业
    学生成绩查询系统个人NABCD
    返回一个整数组的最大子数组和
    个人项目3
    返回一个二维整数组中最大子数组的和
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9879350.html
Copyright © 2011-2022 走看看