bzoj 3569: DZY Loves Chinese II

Description

神校XJ之学霸兮,Dzy皇考曰JC。
摄提贞于孟陬兮,惟庚寅Dzy以降。
纷Dzy既有此内美兮,又重之以修能。
遂降临于OI界,欲以神力而凌♂辱众生。

今Dzy有一魞歄图,其上有N座祭坛,又有M条膴蠁边。
时而Dzy狂WA而怒发冲冠,神力外溢,遂有K条膴蠁边灰飞烟灭。
而后俟其日A50题则又令其复原。(可视为立即复原)
然若有祭坛无法相互到达,Dzy之神力便会大减,于是欲知其是否连通。

题目大意:给定一张图,每次询问去掉几条边之后图是否连通

Solution

先做一棵生成树,然后给每一条非树边随机一个权值
再把每一条树边的权值设为所有跨过这条边的非树边的权值的异或和

如果存在不连通的情况一定是:跨过这条树边的所有非树边和这条边都被去掉了
也就是存在一个子集的权值异或和为 \(0\)

每一次用线性基判断一下就好了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+10;
int n,m,fa[N],head[N],nxt[N*2],to[N*2],num=0,dep[N];bool v[N];
ll x0=914241,mod=1e15,w[N],b[65];int p[20];
inline ll seed(){return x0=(x0*41+19260817)%mod;}
struct data{int x,y;ll w;}e[N];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
inline void dfs(int x,int last){
    for(int u,i=head[x];i;i=nxt[i]){
        if((u=to[i])==last)continue;
        fa[u]=x;dep[u]=dep[x]+1;dfs(u,x);
    }
}
inline void dfs1(int x){
    for(int u,i=head[x];i;i=nxt[i]){
        if((u=to[i])==fa[x])continue;
        w[x]^=w[u];dfs1(u);
    }
}
inline bool ins(ll x){
    for(int i=60;i>=0;i--){
        if(!(x>>i&1))continue;
        if(!b[i]){b[i]=x;return true;}
        else x^=b[i];
        if(!x)return false;
    }
    return false;
}
int main(){
  freopen("pp.in","r",stdin);
  freopen("pp.out","w",stdout);
  srand(19260859);
  int x,y,Q,k,cnt=0;
  cin>>n>>m;
  for(int i=1;i<=n;i++)fa[i]=i;
  for(int i=1;i<=m;i++){
      scanf("%d%d",&x,&y);e[i]=(data){x,y};
      if(find(x)==find(y)){e[i].w=seed();continue;}
      fa[find(y)]=find(x);link(x,y);link(y,x);v[i]=1;
  }
  dfs(1,1);
  for(int i=1;i<=m;i++){
      if(dep[e[i].x]<dep[e[i].y])swap(e[i].x,e[i].y);
      if(v[i])continue;
      w[e[i].x]^=e[i].w;w[e[i].y]^=e[i].w;
  }
  dfs1(1);
  for(int i=1;i<=m;i++)if(v[i])e[i].w=w[e[i].x];
  cin>>Q;
  while(Q--){
      bool flag=1;
      scanf("%d",&k);
      for(int i=1;i<=k;i++)scanf("%d",&p[i]),p[i]^=cnt;
      for(int i=1;i<=k;i++)
          if(!ins(e[p[i]].w)){flag=0;break;}
      if(flag)puts("Connected"),cnt++;else puts("Disconnected");
      memset(b,0,sizeof(b));
  }
  return 0;
}

转载于:https://www.cnblogs.com/Yuzao/p/8721423.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值