G71 可删除线性基+离线处理 P3733 [HAOI2017] 八纵八横

视频链接:G71 可删除线性基+离线处理 P3733 [HAOI2017] 八纵八横_哔哩哔哩_bilibili

 

 

 

G67 线性基+贪心法 P4151 [WC2011] 最大XOR和路径 - 董晓 - 博客园 (cnblogs.com) 

P3733 [HAOI2017] 八纵八横 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

// 可删除线性基+离线处理 O(1000*q)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <bitset>
using namespace std;

const int N=1010;
typedef bitset<N> bit;
int n,m,q,cnt;
int tim[N],del[N],add[N],can[N];
bit p[N],sum[N],val[N];
struct node{
  int x,y;
}a[N];
bool vis[N];
int idx,head[N];
struct E{
  int to,ne; bit w;
}e[N];

void Add(int u,int v,bit w){
  e[++idx].to=v,e[idx].w=w,e[idx].ne=head[u],head[u]=idx;
}
void insert(bit x,int t){
  for(int i=1000;i>=0;i--){
    if(x[i]){
      if(tim[i]<t) //用x替换删除时间早的基
        swap(tim[i],t),swap(p[i],x);
      x^=p[i];
    }
  }
}
void dfs(int x){
  vis[x]=true;
  for(int i=head[x];i;i=e[i].ne){
    int y=e[i].to;
    // 没有搜过y,则继续搜索
    // 否则 把环的异或和插入线性基
    if(!vis[y]) sum[y]=sum[x]^e[i].w, dfs(y);
    else insert(sum[x]^e[i].w^sum[y],N);
  }
}
void print(bit &b){
  int i;
  for(i=1000;i&&!b[i];i--);
  for(;i>=0;i--) putchar('0'+b[i]);
  puts("");
}
void query(int t){
  bit b;
  for(int i=1000;i>=0;i--)
    if(tim[i]>t&&!b[i]) b^=p[i];
  print(b); //输出
}
int main(){
  cin>>n>>m>>q; string s,z;
  for(int i=1,x,y;i<=m;i++){
    cin>>x>>y>>z; bit w(z);
    Add(x,y,w); Add(y,x,w);
  }
  dfs(1); //预处理
  query(0);
  
  for(int i=1;i<=q;i++)del[i]=N; //初始化
  for(int i=1,x,y,k;i<=q;i++){ //离线处理
    cin>>s;
    if(s[1]=='d'){ //Add
      cin>>x>>y>>z; 
      bit w(z);
      add[++cnt]=i; //第k号边的添加时间
      a[cnt]={x,y};
      val[i]=(w^sum[x]^sum[y]); //环值
    }
    else if(s[1]=='h'){ //Change
      cin>>k>>z; 
      bit w(z);
      del[add[k]]=i; //第k号边的删除时间
      val[i]=(w^sum[a[k].x]^sum[a[k].y]); //环值
      add[k]=i; //第k号边的添加时间
    }
    else{ //Cancel
      cin>>k;
      can[i]=1; //是删除操作
      del[add[k]]=i; //第k号边的删除时间
    }
  }
  for(int i=1;i<=q;i++){
    if(!can[i]) insert(val[i],del[i]);
    query(i);
  }
}

 

// 可删除线性基+离线处理 O(1000*q)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <bitset>
using namespace std;

const int N=1010;
typedef bitset<N> bit;
int n,m,q,cnt,tot;
int tim[N],add[N],edg[N],del[N];
pair<int,int>xy[N];
bit p[N],sum[N],val[N];
bool vis[N];
int idx,head[N];
struct E{
  int to,ne; bit w;
}e[N];

void Add(int u,int v,bit w){
  e[++idx].to=v,e[idx].w=w,e[idx].ne=head[u],head[u]=idx;
}
void insert(bit x,int t){
  for(int i=1000;i>=0;i--){
    if(x[i]){
      if(tim[i]<t) //用x替换删除时间早的基
        swap(tim[i],t),swap(p[i],x);
      x^=p[i];
    }
  }
}
void dfs(int x){
  vis[x]=true;
  for(int i=head[x];i;i=e[i].ne){
    int y=e[i].to;
    // 没有搜过y,则继续搜索
    // 否则 把环的异或和插入线性基
    if(!vis[y]) sum[y]=sum[x]^e[i].w, dfs(y);
    else insert(sum[x]^e[i].w^sum[y],N);
  }
}
void print(bit &b){
  int s=0;
  for(int i=1000;i>=0;i--)if(b[i]){s=i;break;}
  for(int i=s;i>=0;i--) putchar('0'+b[i]);
  puts("");
}
void query(int t){
  bit b;
  for(int i=1000;i>=0;i--)
    if(tim[i]>t&&!b[i]) b^=p[i];
  print(b); //输出
}
int main(){
  cin>>n>>m>>q; string s,z;
  for(int i=1,x,y;i<=m;i++){
    cin>>x>>y>>z; bit w(z);
    Add(x,y,w); Add(y,x,w);
  }
  dfs(1); //预处理
  query(0);
  
  for(int i=1;i<=q;i++)del[i]=N; //初始化
  tot=q+1;
  for(int i=1,x,y,k;i<=q;i++){ //离线处理
    cin>>s;
    if(s[1]=='d'){ //Add
      cin>>x>>y>>z; 
      bit w(z);
      add[i]=++cnt; //添加的边
      edg[cnt]=cnt; //边的编号
      val[cnt]=(w^sum[x]^sum[y]); //环值
      xy[cnt]={x,y}; //路径的端点
    }
    else if(s[1]=='h'){ //Change
      cin>>k>>z; 
      bit w(z);
      del[edg[k]]=i; //删除的时间
      add[i]=--tot;  //添加的边
      edg[k]=tot;    //边的编号
      val[tot]=(w^sum[xy[k].first]^sum[xy[k].second]);
    }
    else{ //Cancel
      cin>>k;
      del[edg[k]]=i; //删除的时间
    }
  }
  for(int i=1;i<=q;i++){
    if(add[i]) insert(val[add[i]],del[add[i]]);
    query(i);
  }
}

 

posted @ 2024-07-24 19:32  董晓  阅读(63)  评论(0编辑  收藏  举报