BZOJ 3569: DZY Loves Chinese II(线性基)

传送门

解题思路

  首先构造出一个生成树,考虑不连接的情况。假设连通两点的非树边和树边都断掉后不连通,那么可以给所有的非树边随机一个互不相同的值,然后树边的权值为过他两端点的非树边权值的异或和,这个可以用一个类似树上差分的东西来实现。询问的时候把所有询问的边权加到线性基里,看是否某个数字能被线性表出。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<set>

using namespace std;
const int N=100005;
const int M=500005;
const int INF=(1<<30);

inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    return f?x:-x;
}

int n,m,head[N],cnt,to[N<<1],nxt[N<<1],Q,b[35],F[N];
int tag[N],tot,id[N<<1],ans;
bool flag;
set<int> S;

struct Edge{
    int u,v,w;
}edge[M];

inline void add(int bg,int ed,int Id){
    to[++cnt]=ed,nxt[cnt]=head[bg],id[cnt]=Id,head[bg]=cnt;
}

int get(int x){
    if(x==F[x]) return x;
    return F[x]=get(F[x]);
}

void dfs(int x,int fa){
    for(int i=head[x];i;i=nxt[i]){
        int u=to[i]; if(u==fa) continue;
        dfs(u,x);
        edge[id[i]].w^=tag[u];
        tag[x]^=tag[u]; 
    }
}

inline void init(){
    memset(b,0,sizeof(b));
    flag=false;
}

inline void Insert(int x){
    for(int i=30;~i;i--)
        if(x&(1<<i)){
            if(!b[i]) {b[i]=x; return ;}
            x^=b[i];
        }
    if(!x) flag=1;
}

int main(){
    srand(time(0)); srand(rand()); srand(20020426);
    n=rd(),m=rd();int x,y;
    for(int i=1;i<=n;i++) F[i]=i;
    for(int i=1;i<=m;i++)
        edge[i].u=rd(),edge[i].v=rd();
    for(int i=1;i<=m;i++){
        x=get(edge[i].u); y=get(edge[i].v);
        if(x==y) {
            edge[i].w=rand()%INF;
            while(S.find(edge[i].w)!=S.end()) edge[i].w=rand()%INF;
            S.insert(edge[i].w);
            tag[edge[i].u]^=edge[i].w; 
            tag[edge[i].v]^=edge[i].w;
            continue;
        }
        add(edge[i].u,edge[i].v,i); add(edge[i].v,edge[i].u,i);
        F[x]=y; tot++;
    }   
    dfs(1,0); Q=rd();
    while(Q--){
        init();
        for(x=rd();x;x--) y=(rd()^ans),Insert(edge[y].w);
        if(flag) puts("Disconnected");
        else puts("Connected"),ans++;
    }
    return 0;
}   

猜你喜欢

转载自www.cnblogs.com/sdfzsyq/p/10280458.html
今日推荐