P3733 [HAOI2017] 八纵八横
看到这道题如果做过 P4151 [WC2011] 最大XOR和路径 就很容易想到这个询问的本质 —— 在图上走若干个环使其经过边权异或和最大。
对于任意环,从 \(1\) 走到环上任意点 \(u\) 走一圈后再走回 \(1\),发现 \(1\to u\) 上的边都走了两次异或和为 \(0\),所以剩下的就是环上的边权异或和。
并且最后环是没有重边的,两个有重边的环重边的贡献为 0,剩下的边必定还是一个环。
考虑找到每个环。实际上只需要找到一棵 dfs 树,对于非树边 \((u,v,w)\) 将 \(dis_u\bigoplus dis_v \bigoplus w\) 加入即可,其中 \(dis_u\) 表示从 dfs 树上根到 \(u\) 路径上的异或和。这个手玩一下可以发现无论是走非树边还是返祖边都能通过当前环异或上对应边贡献的环达到目的。
维护可删除线性基,尽量使高位上的基删除时间晚,每一时刻查询即可。
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#define fin(x) freopen(#x".in","r",stdin)
#define fout(x) freopen(#x".out","w",stdout)
#define fr(x) fin(x),fout(x);
#define Fr(x,y) fin(x),fout(y)
#define INPUT(_1,_2,FILE,...) FILE
#define IO(...) INPUT(__VA_ARGS__,Fr,fr)(__VA_ARGS__)
using namespace std;
using namespace __gnu_pbds;
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cfast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define ll long long
#define ull unsigned long long
#define intz(x,y) memset((x),(y),sizeof((x)))
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
#define tup(x) array<int,(x)>
inline ll read(){
ll x=0,f=1;char ch=nc();
while(ch<48||ch>57){if(ch=='-')f=-1;ch=nc();}
while(ch>=48&&ch<=57)x=x*10+ch-48,ch=nc();
return x*f;
}
//void write(int x){cout<<x<<' ';}
//void write(pii x){cout<<"P("<<x.fi<<','<<x.se<<")\n";}
//void write(vector<auto>x){for(auto i:x)write(i);cout<<'\n';}
//void write(auto *a,int l,int r){for(int i=l;i<=r;i++)write(a[i]);cout<<'\n';}
inline ll lowbit(ll x){return x&-x;}
#define B bitset<N>
#define P pair<int,B>
#define pcount(x) __builtin_popcount(x)
inline void max_(ll &x,ll y){if(y>x)x=y;}
inline void min_(ll &x,ll y){if(y<x)x=y;}
const int mod=998244353;
ll qp(ll x,int y){ll res=1;for(;y;x=x*x%mod,y>>=1)if(y&1)res=res*x%mod;return res;}
const int N=2005;
B x[N],dis[N],w[N];int t[N],E[N][2],id[N],tot,ed[N],tot_,q[N];bool vis[N];
vector<P>e[N];
void write(B v){
bool fl=0;
for(int i=1000;~i;i--)
if(fl)cout<<v.test(i);
else if(v.test(i))fl=1,cout<<1;
cout<<'\n';
}
void insert(int tim,B v){
if(!tim)tim=1e9;
for(int i=1000;~i&&tim;i--)if(v.test(i))
(tim>t[i]?swap(t[i],tim),swap(x[i],v),1:0),v^=x[i];
}
void query(int tim){
B res;
for(int i=1000;~i;i--)
if(t[i]>tim&&!res.test(i))res^=x[i];
write(res);
}
void dfs(int u,int fa){
vis[u]=1;
for(P v:e[u])if(v.fi^fa){
if(vis[v.fi])insert(0,dis[u]^dis[v.fi]^v.se);
else dis[v.fi]=dis[u]^v.se,dfs(v.fi,u);
}
}
inline void UesugiErii(){
int n,m,Q;B _;cin>>n>>m>>Q;tot_=Q;
for(int i=1,u,v;i<=m;i++)
cin>>u>>v>>_,e[u].pb(mp(v,_)),e[v].pb(mp(u,_));
dfs(1,0);query(0);
for(int i=1;i<=Q;i++){
string opt;int x,y;B z;cin>>opt>>x;
if(opt=="Add")
cin>>y>>z,++tot,q[i]=id[tot]=tot,
E[tot][0]=x,E[tot][1]=y,w[tot]=dis[x]^dis[y]^z;
else if(opt=="Cancel")ed[id[x]]=i;
else if(opt=="Change"){
cin>>z,ed[id[x]]=i,q[i]=++tot_;
int u=E[id[x]][0],v=E[id[x]][1];
E[tot_][0]=u,E[tot_][1]=v,id[x]=tot_;
w[tot_]=dis[u]^dis[v]^z;
}
}
for(int i=1;i<=Q;query(i),i++)
if(q[i])insert(ed[q[i]],w[q[i]]);
}
signed main(){
//IO();
cfast;
int _=1;//cin>>_;
for(;_;_--)UesugiErii();
return 0;
}

浙公网安备 33010602011771号