P4151 [WC2011]最大XOR和路径

【题意】

给出一个无向图,有边权,求可以重复走的路径的最大的异或和

【分析】

考虑一个链上出现了一个枝杈挂着一个环,那么枝杈上的边会被走两次,贡献为0,而环上的边却全部能取到

所以我们dfs一次把所有环上的异或和放入线性基

然后随意取一条1-n的链,作为初始值,询问线性基构成的最大异或和即可

至于为什么可以随意选一条链? 因为如果有多种1-n的链,他们会构成环,被放入线性基,所以其他情况也被考虑在内了

 

【代码】

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e4+5;
const int maxm=1e5+5;
int n,m;
ll x; 
ll p[105],ans;
struct point
{
    int to,nxt;
    ll v;
}e[maxm<<1];
int head[maxn],vis[maxn],cnt;
void add(int x,int y,ll z)
{
    e[++cnt].to=y; e[cnt].nxt=head[x]; e[cnt].v=z; head[x]=cnt;
    e[++cnt].to=x; e[cnt].nxt=head[y]; e[cnt].v=z; head[y]=cnt;
}
ll del[maxn];
void insert(ll x)
{
    for(int i=60;i>=0;i--)
        if((x>>i)&1)
        {
            if(p[i]) x^=p[i];
            else
            {
                p[i]=x;
                return;
            }
        }
}
void dfs(int u,ll res)
{
    del[u]=res; vis[u]=1;
    for(int i=head[u];i;i=e[i].nxt)
    {
        int to=e[i].to;
        if(!vis[to]) dfs(to,res^e[i].v);
        else insert(res^e[i].v^del[to]);
    }
}
ll query(ll x)
{
    ll res=x;
    for(int i=60;i>=0;i--)
        if((res^p[i])>res)
            res^=p[i];
    return res;
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d%d",&n,&m);
    int x,y; ll z; 
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%lld",&x,&y,&z);
        add(x,y,z);
    }
    dfs(1,0);
    printf("%lld\n",query(del[n]));
    return 0;
}

 

posted @ 2021-05-29 10:36  andyc_03  阅读(51)  评论(0编辑  收藏  举报