BZOJ 2115 [Wc2011] Xor (线性基)

Posted 小坏蛋_千千

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2115 [Wc2011] Xor (线性基)相关的知识,希望对你有一定的参考价值。

Description

考虑一个边权为非负整数的无向连通图,节点编号为 1 到 N,试求出一条从 1 号节点到 N 号节点的路径,使得路径上经过的边权值的 XOR 和最大。

路径可以重复经过某些点或边,当一条边在路径中出现了很多次时,其权值在计算 XOR 和时也要被计算相应多的次数。

 

Input

第一行包含两个整数 N 和 M ,表示该无向图中点的数目与边的数目。

接下来 M 行描述 M 条边,每行三个整数 Si,Ti ,Di,表示 Si 与 Ti 之间存在一条权值为 Di 的无向边。图中可能有重边或自环。

 

Output

仅包含一个整数,表示最大的 XOR 和(十进制结果),注意输出后加换行回车。

 

Sample Input

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

 

Sample Output

6

 

思路

因为是无向图,且允许经过重复点以及重复边,所以我们最终所选择的路径可以看作是从 1 -> n 的一条主路径附带很多的环组成。

记每一个环所贡献的权值为 ai a i ,主路径权值为 disn d i s n ,接下来我们要选择某些 ai a i 使得总权值最大。

显然我们可以找出 ai a i 所代表的线性空间中的一组线性基,然后根据线性基的性质贪心寻找答案。


接下来我们分析为什么这样的做法可行:

  1. 为什么每一个环可以无消耗的加入主路径:具体我们可以从 1 走到环内的一点,然后绕环走完所有的边再原路返回,因为总的权值是各边的异或和,所以来回走同一段路的消耗是 0 ,即每个环的权值我们都可以直接附加到主路径中。
  2. 主路径如何选取:假设从 1 -> n 存在一条以上的路径,那么这些路径之间一定会存在一个或者多个环,此时我们讨论只有一个环的情况(多个环类似),设该环的权值为 p p ,主路径的权值为 dis ,显然另一条路径的权值为 pdis p ⊕ d i s ,而最终我们贪心寻找答案的时候一定会考虑到另一条路径的长度,因此保证结果依然是最大的。

 

AC 代码

#include <bits/stdc++.h>
#define IO                       \\
    ios::sync_with_stdio(false); \\
    cin.tie(0);                  \\
    cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 2e5 + 10;

struct node 
    int from;
    int to;
    int next;
    LL cost;
 edge[maxn << 1];
int head[maxn], tot;
int n, m, idx;
LL a[maxn], dis[maxn], p[maxn];
void init() 
    memset(head, -1, sizeof(head));
    memset(dis, -1, sizeof(dis));
    tot = idx = 0;


void addedge(int u, int v, LL cost) 
    edge[tot].from = u;
    edge[tot].to = v;
    edge[tot].cost = cost;
    edge[tot].next = head[u];
    head[u] = tot++;


void initBase() 
    for (int i = 0; i < idx; i++) 
        for (int j = 62; j >= 0; j--) 
            if ((p[i] >> j) & 1) 
                if (a[j] == 0) 
                    a[j] = p[i];
                    break;
                 else 
                    p[i] ^= a[j];
                
            
        
    


void dfs(int x, LL cost) 
    if (dis[x] == -1)
        dis[x] = cost;
    else 
        p[idx++] = dis[x] ^ cost;
        return;
    
    for (int i = head[x]; i != -1; i = edge[i].next) 
        dfs(edge[i].to, edge[i].cost ^ cost);
    


void solve() 
    dfs(1, 0);
    initBase();
    LL ans = dis[n];
    for (int i = 62; i >= 0; i--)
        ans = max(ans, ans ^ a[i]);
    cout << ans << endl;


int main() 
#ifdef LOCAL_IM0QIANQIAN
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#else
    IO;
#endif // LOCAL_IM0QIANQIAN
    init();
    cin >> n >> m;
    for (int i = 0; i < m; i++) 
        LL u, v, cost;
        cin >> u >> v >> cost;
        addedge(u, v, cost);
        addedge(v, u, cost);
    
    solve();
    return 0;

以上是关于BZOJ 2115 [Wc2011] Xor (线性基)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2115 [Wc2011] Xor

bzoj2115: [Wc2011] Xor

BZOJ2115:[WC2011]Xor——题解

BZOJ 2115: [Wc2011] Xor 线性基

BZOJ2115 [Wc2011] Xor

Bzoj 2115: [Wc2011] Xor