【BZOJ 2322】[BeiJing2011]梦想封印 利用"环基"+线性基特征值
很容易想到离线加边并且把环和链拆开搞(就是对于每个终点求出起点到他的路径(其实就是dfs树),然后bzoj2115),而且维护也很简单,然而我们发现不同的终点可能得到相同的值,这就是我们遇到的最大的问题......继续观察,发现两个终点要么得到的值都不同要么得到的值都相同,所以我们就可以判断两个终点的链值的异或值(如果能被此时的"环基"搞出来就可以删掉一个),然后就60分......
作为一名菜鸡,想到这里就去%题解了,发现我和题解的做法只有去重的时候不同......其实我们就是找到得到的值互不相同的终点的个数,也就是[对于目前的"环基",再插入链值,得到的线性基不同]的终点个数,然后我们发现对于每个终点,判断他们得到的线性基不同就是判断他们在"环基"里插入自己之后自己变成的值(需要经过上下消)不同,这样我们就能通过模拟插入过程得到每个值的"特征值",现在我们只需要找到特征值的种数就可以了(用个set就可以解决)!!!
#include <set> #include <cstdio> #include <cstring> #include <algorithm> char xB[(1<<15)+10],*xS,*xT; #define gtc (xS==xT&&(xT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xT)?0:*xS++) inline void read(int &x){ register char ch=gtc; for(x=0;ch<'0'||ch>'9';ch=gtc); for(;ch>='0'&&ch<='9';x=(x<<1)+(x<<3)+ch-'0',ch=gtc); } typedef long long LL; inline void Read(LL &x){ register char ch=gtc; for(x=0;ch<'0'||ch>'9';ch=gtc); for(;ch>='0'&&ch<='9';x=(x<<1)+(x<<3)+ch-'0',ch=gtc); } const int A=61,N=5010,M=20010; #define bin(a,b) (((a)>>(b))&1) std::set<LL>::iterator it; LL temp[N]; int len; struct Gay{ int size;LL gay[A];std::set<LL> st; inline LL trans(LL x,int begin){ for(int i=begin;i>=0;--i) if(gay[i]&&bin(x,i))x^=gay[i]; return x; } inline void put(LL x){st.insert(trans(x,A-1));} inline void insert(LL x){ for(int i=A-1;i>=0;--i){ if(!bin(x,i))continue; if(gay[i])x^=gay[i]; else{gay[i]=x,++size,len=0; for(it=st.begin();it!=st.end();++it) temp[++len]=trans(*it,i); st.clear(); for(int j=1;j<=len;++j)st.insert(temp[j]); break;} } } inline LL query(){ return st.size()*(1LL<<size)-1; } }gay; struct V{int to,next;LL w;}c[M<<1]; struct E{int a,b;LL c;}e[M]; LL dis[N],ans[M]; bool in[N],die[M]; int head[N],t,n,m,Q,sort[M]; inline void add(int x,int y,LL z){c[++t].to=y,c[t].next=head[x],head[x]=t,c[t].w=z;} inline void dfs(int x,int fa,LL val){ in[x]=true,dis[x]=val,gay.put(val); for(int i=head[x];i;i=c[i].next) if(in[c[i].to])gay.insert(c[i].w^dis[x]^dis[c[i].to]); else dfs(c[i].to,x,val^c[i].w); } int main(){ read(n),read(m),read(Q); register int i;int x; for(i=1;i<=m;++i)read(e[i].a),read(e[i].b),Read(e[i].c); for(i=1;i<=Q;++i)read(x),sort[i]=x,die[x]=true; for(i=1;i<=m;++i)if(!die[i])add(e[i].a,e[i].b,e[i].c),add(e[i].b,e[i].a,e[i].c); dfs(1,0,0); for(i=Q;i>0;--i){ ans[i]=gay.query(),x=sort[i]; add(e[x].a,e[x].b,e[x].c),add(e[x].b,e[x].a,e[x].c); if(in[e[x].a]==false&&in[e[x].b]==false)continue; if(in[e[x].a]&&in[e[x].b])gay.insert(dis[e[x].a]^dis[e[x].b]^e[x].c); else if(in[e[x].a])dfs(e[x].b,e[x].a,dis[e[x].a]^e[x].c); else dfs(e[x].a,e[x].b,dis[e[x].b]^e[x].c); }printf("%lld\n",gay.query()); for(i=1;i<=Q;++i)printf("%lld\n",ans[i]); return 0; }
苟利国家生死以, 岂因祸福避趋之。