洛谷 P4151 BZOJ 2115 [WC2011]最大XOR和路徑

//bzoj上的題面太醜了,致使VJ的題面也很醜,因而這題用洛谷的題面spa

題面描述

XOR(異或)是一種二元邏輯運算,其運算結果當且僅當兩個輸入的布爾值不相等時才爲真,不然爲假。 XOR 運算的真值表以下(\(1\) 表示真, \(0\) 表示假):
code

而兩個非負整數的 XOR 是指將它們表示成二進制數,再在對應的二進制位進行 XOR 運算。blog

譬如 \(12\) XOR \(9\) 的計算過程以下:io

\(12\) XOR \(9\) = 5$。class

容易驗證, XOR 運算知足交換律與結合律,故計算若干個數的 XOR 時,不一樣的計算順序不會對運算結果形成影響。從而,能夠定義 \(K\) 個非負整數 \(A_1,A_2,……,A_{K-1},A_K\)的 XOR 和爲test

\(A_1\) XOR \(A_2\) XOR …… XOR \(A_{K-1}\) XOR \(A_K\)搜索

考慮一個邊權爲非負整數的無向連通圖,節點編號爲 \(1\)\(N\),試求出一條從 \(1\) 號節點到 \(N\) 號節點的路徑,使得路徑上通過的邊的權值的 XOR 和最大。二進制

路徑能夠重複通過某些點或邊,當一條邊在路徑中出現了屢次時,其權值在計算 XOR 和時也要被計算相應多的次數,具體見樣例。im

輸入格式

輸入文件 xor.in 的第一行包含兩個整數 \(N\)\(M\), 表示該無向圖中點的數目與邊的數目。數據

接下來 \(M\) 行描述 \(M\) 條邊,每行三個整數 \(S_i\)\(T_i\)\(D_i\), 表示 \(S_i\)\(T_i\) 之間存在一條權值爲 \(D_i\) 的無向邊。

圖中可能有重邊或自環。

輸出格式

輸出文件 xor.out 僅包含一個整數,表示最大的 XOR 和(十進制結果)。

輸入輸出樣例

輸入 #1

5 7
 1 2 2
 1 3 2
 2 4 1
 2 5 1
 4 5 3
 5 3 4
 4 3 2

輸出 #1

6

說明/提示

【樣例說明】

如圖,路徑\(1 \rightarrow 2 \rightarrow 4 \rightarrow 3 \rightarrow 5 \rightarrow 2 \rightarrow 4 \rightarrow 5\)對應的XOR和爲

\(2\) XOR \(1\) XOR \(2\) XOR \(4\) XOR \(1\) XOR \(1\) XOR \(3 = 6\)

固然,一條邊數更少的路徑\(1 \rightarrow 3 \rightarrow 5\)對應的XOR和也是\(2\) XOR \(4 = 6\)

【數據規模】

對於 \(20 \%\) 的數據,\(N \leq 100,M \leq 1000,D_i \leq 10^{4}\)

對於 \(50 \%\) 的數據,\(N \leq 1000,M \leq 10000,D_i \leq 10^{18}\)

對於 \(70 \%\) 的數據,\(N \leq 5000,M \leq 50000,D_i \leq 10^{18}\)

對於 \(100 \%\) 的數據,\(N \leq 50000\)\(M \leq 100000\)\(D_i \leq 10^{18}\)

解題思路

看了題解可知,這題先dfs一遍圖,隨便找一條從起點到終點的路,求出路上的異或值,同時把全部搜索到的環的異或值所有加入線性基,而後把那條路上的異或值放到線性基裏,找可以異或到的最大值,而後就是答案。敷衍

這題的思想有點像我這學期高數剛學的格林公式,不知道的就別管這個詞了。咱們從那條路起點\(1\)出發,到達路中間的一個點\(x\),而後離開這條路,經過某一段 \(x \rightarrow y\) 走到某個環上的一個點\(y\),而後從點\(y\)開始繞環一週,回到點\(y\),再從點\(y\)經過剛纔那段\(y \rightarrow x\) 回到點\(x\),再接着走完那條路剩下的部分\(x\rightarrow n\)。由「異或兩次同一個數至關於沒有異或」的性質能夠知道,\(x\rightarrow y\)\(y\rightarrow x\)就互相抵消了,因而答案就是\(1\rightarrow n\)的異或值再異或上那個環的異或值。再多走幾個環,就再多異或幾個環就好。

那麼爲何最開始隨便選一條路就好呢?是這樣:假設存在兩條路能夠從\(1\)\(n\),那麼由於是無向圖,這兩條路就成了一個環,咱們dfs過程當中就會把這個環加入線性基。走了其中一條路,再走這個環,就至關於走了另外一條路。

源代碼

#include<stdio.h>

const int MAXN=5e5+5,MAXM=4e5+5;
typedef long long ull;
int n,m;

struct Edge{
    int nxt,to;
    ull w;
}e[MAXM<<1];
int cnt=1,head[MAXN];
inline void add(int u,int v,ull w)
{
    e[cnt]={head[u],v,w};
    head[u]=cnt++;
    e[cnt]={head[v],u,w};
    head[v]=cnt++;
}


ull b[64]={0};//線性基
inline void addb(ull a)
{
    for(int i=62;~i;i--)
    {
        if(a>>i)
        {
            if(b[i]) a^=b[i];
            else
            {
                b[i]=a;
                return;
            }
        }
    }
}
inline ull mx(ull ans)
{
    for(int i=62;~i;i--)
        if((ans^b[i])>ans) ans^=b[i];
    return ans;
}
bool vis[MAXN];
ull dis[MAXN];//從1搜過來的值
void dfs(int u)
{
    vis[u]=1;
    for(int i=head[u];i;i=e[i].nxt)
    {
        int v=e[i].to;
        if(vis[v])
            addb(dis[v]^dis[u]^e[i].w);
        else
        {
            dis[v]=dis[u]^e[i].w;
            dfs(v);
        }
    }
}
int main()
{
    //freopen("test.in","r",stdin);
    scanf("%d%d",&n,&m);
    while(m--)
    {
        int u,v;
        ull w;
        scanf("%d%d%lld",&u,&v,&w);
        add(u,v,w);
    }
    dfs(1);
    printf("%lld\n",mx(dis[n]));
    return 0;
}
相關文章
相關標籤/搜索