P4151 [WC2011] 线性基 + DFS

58 篇文章 0 订阅
题意

传送门 P4151 [WC2011]最大XOR和路径

题解

异或运算和与运算、或运算不同,没有单调性,难以使用一般求最短路的方法求解此问题。

考虑环,显然图中环的异或值都是可以取到的。考虑两种情况,环不在路径上,那么可以反复经过某一条通向环的路径,且此路径没有贡献;环在路径上,那么将换上的原路径部分替换为环上非原路径的部分。那么 D F S DFS DFS 求图中所有简单环的异或值,构造线性基。任取一条 1 → N 1\rightarrow N 1N 的路径,从高位向低位不断尝试异或这一位的线性基,求最大值即可。

由于求解最大值时从高位向低位依次处理,构造线性基时只用保证第 i i i 对应的线性基的高位为零即可,不一定要消去第 i i i 位其余的 1 1 1

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define maxl 60
#define maxn 50005
typedef long long ll;
struct edge
{
    int to;
    ll cost;
};
int N, M;
ll dis[maxn], B[maxl + 1];
bool used[maxn];
vector<edge> G[maxn];

void insert(ll n)
{
    for (int i = maxl; i >= 0; --i)
    {
        if (n >> i & 1)
        {
            if (B[i])
                n ^= B[i];
            else
            {
                B[i] = n;
                break;
            }
        }
    }
}

void dfs(int p, int v, ll d)
{
    used[v] = 1, dis[v] = d;
    for (int i = 0; i < (int)G[v].size(); ++i)
    {
        edge &e = G[v][i];
        if (!used[e.to])
            dfs(v, e.to, d ^ e.cost);
        else if (e.to != p)
            insert(d ^ e.cost ^ dis[e.to]);
    }
}

int main()
{
    scanf("%d%d", &N, &M);
    for (int i = 0; i < M; ++i)
    {
        int s, t;
        ll d;
        scanf("%d%d%lld", &s, &t, &d);
        G[s].push_back(edge{t, d});
        G[t].push_back(edge{s, d});
    }
    dfs(0, 1, 0);
    ll res = dis[N];
    for (int i = maxl; i >= 0; --i)
        if (!(res >> i & 1))
            res ^= B[i];
    printf("%lld\n", res);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值