羅区P4151 BZOJ 2115 [WC2011] XORと最大パス

// bzoj醜い顔にタイトル、VJも醜い直面する問題を引き起こし、そのロスバレーでこの問題の顔の問題

説明フェイス質問

XOR(排他的OR)は、二値論理演算、場合に限り、等しくない場合は、真の二つの入力のブールはfalse計算結果です。XOR演算の次の真理値表(\(1 \)が trueを表す\(0 \)は falseを示します):

XOR二非負整数は二進数にそれらを示し、そして、対応するビットにおいてXOR演算を行うことをいいます。

例えば、\(12は\) XOR \(9 \)を次のように計算されます。

したがって、\(12 \である) XOR \(9 \) = 5 $。

検証が容易である場合、XOR演算は、可換と連想であるので、XOR演算の複数の数は、異なる演算シーケンスは、計算結果に影響を及ぼしません。このように、定義することができる(K \)\非負整数(A_1、A_2、...、\ A_ {K-1}、A_K \) XORのであり

\(A_1 \) XOR \(A_2 \) XOR ...... XOR \(A_ {K-1} \) XOR \(A_K \)

非負整数辺の重みは、ノード番号接続されたグラフを無向考える\(1 \)をする(N \)を\サンプルがから得られる、\(1 \)への米国特許第ノード(N \)\ノードの数をパス、このようなXORの最大重量そのパスのエッジ上を通過。

エッジがパスに複数回表示されたときに、いくつかのパスが特定の例を参照して、XORを計算し、また、複数のそれぞれの時間を計算する際に、ポイント又はエッジを介してその重量を繰り返すことができます。

入力形式

入力ファイルの最初の行は、二つ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;
}

おすすめ

転載: www.cnblogs.com/wawcac-blog/p/11324239.html