BZOJ3569 DZY Loves Chinese II

DZY Loves Chinese II

给一张无向图,每次删掉一些边(非永久操作),问图是否连通。

N≤100000 M≤500000 Q≤50000 1≤K≤15

数据保证没有重边与自环

题解

取一个生成树,对每条非树边取一个随机权值,对每条树边设为“覆盖它的所有非树边”的权值的xor,这个可以用类似树上差分的方式实现。

对于每次询问,只要某个子集的所有边xor值是0,那么就不连通,否则连通。

判断用线性基就好了。时间复杂度\(O(n+\Sigma k \times 64)\)。

#include<bits/stdc++.h>
#define co const
#define il inline
template<class T> T read(){
    T x=0,w=1;char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*w;
}
template<class T> T read(T&x){
    return x=read<T>();
}
using namespace std;
typedef long long LL;

il LL van(){
    return rand()|rand()<<15|(LL)rand()<<30|(LL)rand()<<45|(LL)rand()<<60;
}

co int N=100000+10;
int n,m;
struct edge{int y,next;}pool[10*N];
int head[N],tot;

il void add_edge(int x,int y){
    pool[++tot]=(edge){y,head[x]},head[x]=tot;
}
int dep[N],adj[N];
LL dif[N],val[5*N];
void dfs(int x,int fa){
    for(int i=head[x];i;i=pool[i].next){
        int y=pool[i].y;
        if(y==fa) continue;
        if(!dep[y]){
            dep[y]=dep[x]+1,adj[y]=(i+1)>>1;
            dfs(y,x),
            dif[x]^=dif[y];
        }
        else if(dep[y]<dep[x]){
            int id=(i+1)>>1;
            val[id]=van();
            dif[x]^=val[id],dif[y]^=val[id];
        }
    }
    val[adj[x]]=dif[x];
}

LL bas[64];
bool insert(LL v){
    for(int i=63;v&&i>=0;--i)if(v>>i&1){
        if(!bas[i]) return bas[i]=v,1;
        else v^=bas[i];
    }
    return 0;
}
int main(){
    srand(20030506);
    read(n),read(m);
    for(int i=1;i<=m;++i){
        int x=read<int>(),y=read<int>();
        add_edge(x,y),add_edge(y,x);
    }
    dfs(1,0);
    int ans=0;
    for(int q=read<int>();q--;){
        int k=read<int>();
        bool valid=1;
        memset(bas,0,sizeof bas);
        for(int i=1;i<=k;++i)
            if(!insert(val[read<int>()^ans])) valid=0;
        ans+=valid,puts(valid?"Connected":"Disconnected");
    }
    return 0;
}
上一篇:008-redis应用-01-分布式锁


下一篇:redis理论部分