BZOJ.2115.[WC2011]Xor(線性基)
阿新 • • 發佈:2018-07-10
ret cpp tps span sdi query 但是 統計 https
即我們可以任意選取一條1->n的路徑(反復走顯然沒啥用),如果它不更優,會在與某個環Xor後換成一條更優的路徑。(同理,對於路徑上點的選擇也是任意的。所有環都要算上)
題目鏈接
\(Description\)
給定一張無向帶邊權圖(存在自環和重邊)。求一條1->n的路徑,使得路徑經過邊的權值的Xor和最大。可重復經過點/邊,且邊權和計算多次。
\(Solution\)
來找一些性質。從一個點出發,到達任意一個點後原路返回,那麽得到的和仍為0。但是如果走完一個環後原路返回,則會得到這個環的Xor和。
那麽從1點就可以得到任何一個環的Xor和。我們還需要一條1->n的路徑,使得搭配上某些環後答案最大。於是我們就可以對環的權值構造線性基,拿路徑Xor和在上面求最大值。
選取哪條路徑呢?如果存在多條1->n的路徑,實際上任意兩條也構成了一個環,我們也已統計在內了。
//6016kb 500ms #include <cstdio> #include <cctype> #include <algorithm> //#define gc() getchar() #define MAXIN 100000 #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) typedef long long LL; const int N=5e4+5,M=2e5+5; int n,Enum,H[N],nxt[M],to[M]; LL base[69],len[M],val[N]; bool vis[N]; char IN[MAXIN],*SS=IN,*TT=IN; inline int read() { int now=0;register char c=gc(); for(;!isdigit(c);c=gc()); for(;isdigit(c);now=now*10+c-'0',c=gc()); return now; } inline LL readll() { LL now=0;register char c=gc(); for(;!isdigit(c);c=gc()); for(;isdigit(c);now=now*10+c-'0',c=gc()); return now; } inline void AddEdge(LL w,int u,int v) { to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, len[Enum]=w; to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, len[Enum]=w; } inline void Insert(LL x) { for(int i=60; ~i; --i) if(x&(1ll<<i)) { if(base[i]) x^=base[i]; else {base[i]=x; break;} } } inline LL Query(LL x) { for(int i=60; ~i; --i) x=std::max(x,x^base[i]); return x; } void DFS(int x,int f) { vis[x]=1; for(int i=H[x],v; i; i=nxt[i]) if(!vis[v=to[i]]) val[v]=val[x]^len[i], DFS(v,x); else if(v!=f) Insert(val[v]^val[x]^len[i]); } int main() { n=read(); for(int i=1,m=read(); i<=m; ++i) AddEdge(readll(),read(),read()); DFS(1,1); printf("%lld\n",Query(val[n])); return 0; }
BZOJ.2115.[WC2011]Xor(線性基)