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); } }