洛谷P4151 [WC2011]最大XOR和路径(线性基)
不知道线性基是什么东西的可以看看蒟蒻的总结
首先看到异或就想到线性基
我们考虑有一条路径,那么从这条路径走到图中的任意一个环再走回这条路径上,对答案的贡献是这个环的异或和,走到这个环上的路径对答案是没有影响的
以这张(偷来的)图为例
从$1$走到$n$,先走到环再走回来,那么到环上那条路径(红色的)被走了两次,那么异或之后为0,对答案无贡献
那么我们可以随意走一条路径,然后把图上所有环丢到线性基里,求一下在这些线性基下最大能异或和是多少,就是个板子了
那么考虑一下走的路径会不会对答案有影响
依然考虑(盗来的)图
一开始走的是$B$这条路径,但实际上$A$更优,那么$B$路径异或上这整个大环的权值就是$A$路径的权值
找环可以直接dfs
然后没有然后了
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #define ll long long 6 using namespace std; 7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 8 char buf[1<<21],*p1=buf,*p2=buf; 9 inline ll read(){ 10 #define num ch-'0' 11 char ch;bool flag=0;ll res; 12 while(!isdigit(ch=getc())) 13 (ch=='-')&&(flag=true); 14 for(res=num;isdigit(ch=getc());res=res*10+num); 15 (flag)&&(res=-res); 16 #undef num 17 return res; 18 } 19 ll b[65]; 20 void insert(ll x){ 21 for(int i=63;i>=0;--i){ 22 if((x>>i)&1){ 23 if(!b[i]){ 24 b[i]=x;return; 25 } 26 x^=b[i]; 27 } 28 } 29 } 30 ll query(ll x){ 31 ll res=x; 32 for(int i=63;i>=0;--i) 33 if((res^b[i])>res) res^=b[i]; 34 return res; 35 } 36 const int N=5e4+5,M=2e5+5; 37 int head[N],Next[M],ver[M],tot;ll edge[M]; 38 inline void add(int u,int v,ll e){ 39 ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e; 40 } 41 int vis[N];ll del[N]; 42 void dfs(int u,ll res){ 43 del[u]=res,vis[u]=1; 44 for(int i=head[u];i;i=Next[i]) 45 if(!vis[ver[i]]) dfs(ver[i],res^edge[i]); 46 else insert(res^edge[i]^del[ver[i]]); 47 } 48 int main(){ 49 // freopen("testdata.in","r",stdin); 50 int n,m,u,v;ll e;n=read(),m=read(); 51 for(int i=1;i<=m;++i) 52 u=read(),v=read(),e=read(),add(u,v,e),add(v,u,e); 53 dfs(1,0); 54 printf("%lld\n",query(del[n])); 55 return 0; 56 }
深深地明白自己的弱小