P4151 [WC2011]最大XOR和路徑 題解
阿新 • • 發佈:2022-05-20
首先考慮沒有環的情況,那麼答案肯定就是 \(1\) 到 \(n\) 簡單路徑的邊權異或和。如果出現環,設這個環邊權異或和為 \(c\),從這條 \(1\) 到 \(n\) 簡單路徑到這個環的路徑邊權異或和為 \(k\),那麼答案為 \(dis_n\oplus k\oplus c\oplus k\)。
通過上面的分析,可以發現,答案就是 \(dis_n\) 與所有環的異或和這些數能夠異或起來的最大值,這顯然可以使用線性基來快速解決。注意 \(dis_n\) 是任意一條 \(1\) 到 \(n\) 的路徑異或和即可,因為如果還有其他路徑,一定會出現在環的那部分內,貢獻是一樣的。複雜度 \(O(n\log v)\)
點選檢視程式碼
#include<iostream> #include<cstdio> typedef long long ll; inline ll rd(){ ll res=0;char c=getchar(); for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar())res=(res<<1)+(res<<3)+(c-'0'); return res; } const int N=1e5+13,M=62+13; struct Onbase{ ll p[M]; inline void insert(ll x){ for(int i=62;i>=0;--i){ if(!(x&(1ll<<i))) continue; if(!p[i]){p[i]=x;break;} x^=p[i]; } } }Base; struct Edge{int v;ll w;int nxt;}e[N<<1]; int n,m,h[N],tot; ll dis[N]; bool vis[N]; inline void add_edge(int u,int v,ll w){e[++tot]=(Edge){v,w,h[u]};h[u]=tot;} void dfs(int u,ll x){ vis[u]=1,dis[u]=x; for(int i=h[u];i;i=e[i].nxt){ int v=e[i].v;ll w=e[i].w; if(!vis[v]) dfs(v,x^w); else Base.insert(dis[v]^x^w); } } int main(){ n=rd(),m=rd(); for(int i=1;i<=m;++i){ int u=rd(),v=rd();ll w=rd(); add_edge(u,v,w),add_edge(v,u,w); } dfs(1,0); ll ans=dis[n]; for(int i=62;i>=0;--i) if((ans^Base.p[i])>ans) ans^=Base.p[i]; printf("%lld\n",ans); return 0; }