zoukankan      html  css  js  c++  java
  • [bzoj3569]DZY Loves Chinese II

    若原图不连通,显然答案都是"Disconnected",不妨假设原图连通

    任求一棵生成树,对每条非树边随机一个权值,并将树边的权值为所有"包含"其的非树边("包含"指树边在非树边两端点生成树的路径上),那么每一条边即都有一个边权

    下面,只需要判定删除的边权是否存在非空子集异或和为0即可(存在即不连通)

    具体实现上,随机值范围在long long中即可,求树边的权值可以差分,判定使用线性基即可

    时间复杂度为$o(m+qklog V)$(其中$V$为随机值范围),可以通过

    关于其的正确性,证明来自于这篇blog,摘抄如下——

    必要性:

    若删掉边后的图不连通,任选其中一个极大连通块$S$,考虑$S$和$complement_{V}S$(其中$V$为原图点集)之间的边,显然存在(指非空)且都被删除,下面只需要说明这些边异或和为0

    关于这个,考虑所有非树边(包括不在$S$和$complement_{V}S$之间的边),对其分类讨论:

    1.在$S$或$complement_{V}S$内部,将其两端点生成树的路径上$S$和$complement_{V}S$之间的边取出,由于每一条这样的边都会改变其所属的集合,而最终其所属集合没有变化,那么必然是偶数条,即其贡献为0

    2.在$S$和$complement_{V}S$之间的边,同理取出这些边,必然是奇数条,即其贡献也为0

    综上,即得证

    充分性:

    考虑一个异或和为0的非空边集,将其中的树边先删除,即将生成树划分为若干个连通块(不考虑非树边)

    对这些连通块黑白染色,要求使得任意一条被删除的树边两端点所属连通块不同色

    此时,考虑一条未被删除的非树边,在忽略随机的值很特殊的情况下,可以认为其两端点生成树的路径上在此边集中的边为偶数条,也即其所连结的两个连通块同色

    由此,不难发现不同色的点对之间一定没有(未被删除的)边,也即这两个集合不连通,同时由于边集非空,即总存在树边,那么两个集合都非空

    综上,即得证

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 #define M 500005
     5 #define L 63
     6 #define ll long long
     7 struct Edge{
     8     int nex,to;
     9 }edge[M<<1];
    10 int E,n,m,q,x,y,ans,head[N],dfn[N];
    11 ll z,a[L],val[M],sum[N];
    12 void add(int x,int y){
    13     edge[E].nex=head[x];
    14     edge[E].to=y;
    15     head[x]=E++;
    16 }
    17 void dfs1(int k,int fa){
    18     dfn[k]=++dfn[0];
    19     for(int i=head[k];i!=-1;i=edge[i].nex)
    20         if (edge[i].to!=fa){
    21             if (!dfn[edge[i].to])dfs1(edge[i].to,k);
    22             else{
    23                 if (dfn[k]<dfn[edge[i].to])continue;
    24                 for(int j=0;j<L;j++)val[(i>>1)]=(val[(i>>1)]<<1)+rand()%2;
    25                 sum[k]^=val[(i>>1)],sum[edge[i].to]^=val[(i>>1)];
    26             }
    27         }
    28 }
    29 void dfs2(int k,int fa){
    30     dfn[k]=++dfn[0];
    31     for(int i=head[k];i!=-1;i=edge[i].nex)
    32         if (!dfn[edge[i].to]){
    33             dfs2(edge[i].to,k);
    34             val[(i>>1)]=sum[edge[i].to];
    35             sum[k]^=sum[edge[i].to];
    36         }
    37 }
    38 int main(){
    39     scanf("%d%d",&n,&m);
    40     memset(head,-1,sizeof(head));
    41     for(int i=1;i<=m;i++){
    42         scanf("%d%d",&x,&y);
    43         add(x,y);
    44         add(y,x);
    45     }
    46     dfs1(1,0);
    47     scanf("%d",&q);
    48     for(int i=1;i<=n;i++)
    49         if (!dfn[i]){
    50             while (q--)printf("Disconnected
    ");
    51             return 0;
    52         }
    53     memset(dfn,0,sizeof(dfn));
    54     dfs2(1,0);
    55     while (q--){
    56         scanf("%d",&x);
    57         memset(a,0,sizeof(a));
    58         int tot=0;
    59         for(int i=1;i<=x;i++){
    60             scanf("%d",&y);
    61             z=val[(y^ans)-1];
    62             for(int j=L-1;j>=0;j--)
    63                 if (z&(1LL<<j)){
    64                     if (!a[j]){
    65                         a[j]=z;
    66                         tot++;
    67                     }
    68                     z^=a[j];
    69                 }
    70         }
    71         if (tot<x)printf("Disconnected
    ");
    72         else{
    73             printf("Connected
    ");
    74             ans++;
    75         }
    76     }
    77 }
    View Code
  • 相关阅读:
    HTML5的智能提示在VisualStudio2010
    浏览器的缓存机制
    等待资源(wait_resource)解码(完整版)
    对quartz的总结
    利用Spring动态对Quartz定时任务管理
    Tomcat源码分析(一)服务启动
    深入分析 Java 中的中文编码问题
    企业搜索引擎开发之连接器connector(一)
    SpringQuartz (一)
    Quartz 项目应用笔记
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15024702.html
Copyright © 2011-2022 走看看