• 随机算法瞎练BZOJ3237&3563&3569三倍经验题


    随机方法真的好骚啊O(∩_∩)O~

    最早的时候miaom提出一个奇怪的东西:

    判断一个数列中是否有0/1/2个数出现奇数次

    对每个数赋一个随机权值,异或乱搞,对于判2的情况用一个(可能类似线性基的)方法做一下

    然后我就开始瞎bb:能不能在边或点上赋一些随机权,做一些图论的判定性问题

    (*^▽^*)判断无向图联通

    首先考虑建一棵生成树,则任何破坏连通性的操作都需要破坏这棵树上的边

    要使图不联通,肯定有一棵子树掉下来了

    而子树掉下来的条件是它的根到根的父亲的边断开,且连接子树和树外点的非树边断开

    这是个很好的性质,可以用来搞事情

    对于树外的边都赋上一个随机权值,每个点的权值就是与之相连的非树边的权值异或和

    树上边的权值是它下面的子树所有点的异或和

    那么一来,一些边(恰好)切下一个子树的条件就是异或和=0

    不难发现每次切下的边数很少,3237中只有4,不妨枚举所有子集,看看是否恰好切割

    剩下两题有15,不妨用线性基维护,能组合出0的条件是一个数没用(扫到最后还没有被加入线性基)

    没啦

    made这破bzoj不兹磁time(0)还报RE,害我调了一下午

    这里只贴出3569的代码(前两个没保存,直接改上去了)

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int n,m,p,q,E,Q;
     4 struct edge
     5 {
     6     int from,to;
     7 } e[1000001];
     8 struct bas
     9 {
    10     int a[32];
    11     bool over;
    12     bas()
    13     {
    14         for(int i=0;i<=31;i++)
    15             a[i]=0;
    16         over=0;
    17     }
    18     void add(int x)
    19     {
    20         if(over) return;
    21         for(int i=31;i>=0;i--)
    22         if(x>>i) 
    23         if(a[i]) x^=a[i];
    24         else
    25         {
    26             a[i]=x;
    27             return;
    28         }
    29         over=1;
    30     }
    31 } ret;
    32 int w[1000001],wei[1000001],fa[1000001];
    33 int nex[1000001],fir[1000001];
    34 bool vis[1000001];
    35 void build(int now,int fat)
    36 {
    37     fa[now]=fat;vis[now]=1;
    38     for(int i=fir[now];i;i=nex[i])
    39     if(!vis[e[i].to])
    40         build(e[i].to,now);
    41 }
    42 int dfs(int now)
    43 {
    44     for(int i=fir[now];i;i=nex[i])
    45     if(fa[e[i].to]==now)
    46         w[now]^=dfs(e[i].to);
    47     return w[now];
    48 }
    49 void add(int x,int y)
    50 {
    51     e[++E].from=x;e[E].to=y;nex[E]=fir[x];fir[x]=E;
    52     e[++E].from=y;e[E].to=x;nex[E]=fir[y];fir[y]=E;
    53 } 
    54 int main()
    55 {
    56     scanf("%d%d",&n,&m);
    57     for(int i=1;i<=m;i++)
    58         scanf("%d%d",&p,&q),add(p,q);
    59     build(1,0);
    60     srand(2333);
    61     for(int i=1;i<=E;i+=2)
    62     if(fa[e[i].from]!=e[i].to && fa[e[i].to]!=e[i].from)
    63     {
    64         wei[i]=rand()*32768+rand();
    65         w[e[i].from]^=wei[i];
    66         w[e[i].to]^=wei[i];
    67     }
    68     dfs(1);
    69     
    70     for(int i=1;i<=E;i+=2)
    71     if(fa[e[i].from]==e[i].to)
    72         wei[i]=w[e[i].from];
    73     else
    74     if(fa[e[i].to]==e[i].from)
    75         wei[i]=w[e[i].to];
    76     
    77     scanf("%d",&Q);
    78     int key=0;
    79     for(int i=1;i<=Q;i++)
    80     {
    81         if(i==5)
    82             int e=1; 
    83         scanf("%d",&p);
    84     //    p^=key;
    85         ret=bas();
    86         for(int j=1;j<=p;j++)
    87             scanf("%d",&q),q^=key,
    88             ret.add(wei[q*2-1]);
    89         if(!ret.over) key++;
    90         puts(ret.over?"Disconnected":"Connected");
    91     }
    92     return 0;
    93  } 
  • 相关阅读:
    sublime打开txt文件乱码的问题
    while循环小例
    mongoDB内置文档定义
    WebStorm 10.0.3注册码
    angularjs之ng-mode获取lobject类型里的键值
    前端打印console
    js去掉数组的空字符串
    js数组去重的三种方式的比较
    js数据类型之判断
    Bootstrap中的datetimepicker浅谈
  • 原文地址:https://www.cnblogs.com/wanglichao/p/7260342.html
Copyright © 2020-2023  润新知