[WC2011]最大XOR和路徑,洛谷P4151,線性基+Dfs
阿新 • • 發佈:2018-11-09
正題
這一題挺水的?
直接隨便求一條1到n的路徑異或和,建出Dfs樹,每一條返祖邊與兩點之間路徑異或和組成環,扔進線性基,最後維護一遍即可。
首先證明為什麼只用扔返祖環和為什麼可以扔環?
先解決第二個問題,每一個環肯定可以從1走到其中的某個點上,遍歷一遍這個環,在從開始遍歷的那個點回去。
那麼1到這個點就被遍歷了兩遍,異或和為0,剩下的環算了一次異或值。
然後解決第一個問題,因為不是返祖環的環可以有返祖環異或而成。很明顯,自己畫圖即可。
那麼我們證明了只有環才能帶來價值。
最後,為什麼隨便選一條路徑?
因為如果有多條路徑,那麼他們兩兩成環,肯定可以異或出來另一條路徑。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> using namespace std; int n,m; struct edge{ int y,next; long long c; }s[200010]; int first[50010],len=0; bool tf[50010]; long long dis[50010]; long long p[65]; void ins(int x,int y,long long c){ len++; s[len]=(edge){y,first[x],c};first[x]=len; } void insert(long long x){ for(int i=63;i>=0;i--) if(x>>i){ if(p[i]) x^=p[i]; else {p[i]=x;break;} } } void dfs(int x,long long t){ tf[x]=true;dis[x]=t; for(int i=first[x];i!=0;i=s[i].next) if(tf[s[i].y]) insert(t^s[i].c^dis[s[i].y]); else dfs(s[i].y,dis[x]^s[i].c); } int main(){ scanf("%d %d",&n,&m); int x,y; long long c; for(int i=1;i<=m;i++){ scanf("%d %d %lld",&x,&y,&c); ins(x,y,c); ins(y,x,c); } dfs(1,0); long long ans=dis[n]; for(int i=63;i>=0;i--) ans=max(ans,ans^p[i]); printf("%lld",ans); }