bzoj2115 [Wc2011] Xor(图论+线性基)

题目链接

分析:
首先有一个小技巧,是本题的关键:

任意一条 1 1 n的路径的异或和,都可以由任意一条 1 1 n路径的异或和与图中的一些环的异或和来组合得到

这个怎么理解呢 ?
我们可以找到一条主干线
而路上有环都可以归结成一下情况:
这里写图片描述

权值就是一条单路径(1->n)+所有环
一遍dfs把ta们求出来就可以了
复杂度O(n+m)
求出线性基,里面存储的就是各个环的xor值

因为我们用高斯消元把线性基消成了上三角形,所以在统计答案的时候
需要判断一下: if (b[j]&&((ans^b[j])>ans))

tip

注意a数组的大小
因为dis是ll类型的,以后判断该位上是否是一的时候都这么写:a[i]>>j&1

#include<bits/stdc++.h>
#define ll long long

using namespace std;

const int N=50005;
struct node{
    int y,nxt;
    ll v;
};
node way[N<<2];
int st[N],tot=0,n,m,cnt=0;
ll a[N*20],b[100],dis[N];
bool vis[N];

void add(int u,int w,ll z) {
    tot++;way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;
    tot++;way[tot].y=u;way[tot].v=z;way[tot].nxt=st[w];st[w]=tot;
}

void dfs(int now) {
    vis[now]=1;
    for (int i=st[now];i;i=way[i].nxt) 
        if (vis[way[i].y]) {               //环 
            a[++cnt]=dis[now]^dis[way[i].y]^way[i].v;
        } else {
            dis[way[i].y]=dis[now]^way[i].v;
            dfs(way[i].y);
        }
}

void cal() {
    ll ans=dis[n];               //主干线 
    for (int i=1;i<=cnt;i++) 
        for (int j=63;j>=0;j--) 
            if (a[i]>>j&1) {
                if (b[j]) a[i]^=b[j];
                else {
                    b[j]=a[i];
                    break;
                }
            }
    for (int j=63;j>=0;j--) 
        if (b[j]&&((ans^b[j])>ans))
            ans^=b[j];
    printf("%lld",ans);
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++) {
        int u,w;ll z;
        scanf("%d%d%lld",&u,&w,&z);
        add(u,w,z);
    }
    dfs(1);
    cal();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值