[bzoj 2115]线性基+图论

怎甘沉沦 提交于 2020-02-08 11:25:18

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2115

给定一个带权无向图,要找出从1到n路径权值异或和最大的那一条的路径异或和。

考虑1到n的任意一条路径,都可以表示为1到n的一条路径,加上图上任意的一些环(1所在的那个连通块)。之所以可以这样,是因为图是连通的,而且无向的,走过去也可以走回来,所以假设当前走到了i号点,我想去走一些环,那么可以i->j->在环j上走一圈->j->i,这条路径上仅仅是异或上了一次环的权值(i->j和j->i的权值被抵消了)。

所以就把所有的环插入线性基就好了。最大值可以从高位到低位贪心来搞。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

const int maxn=50005;
const int maxm=100005*2;

vector< pair<int,ll> > G[maxn];
ll a[maxn];

vector<ll> base;
void insert(ll x)
{
    for (int i=0;i<base.size();i++) x=min(x,x^base[i]);
    if (x) base.push_back(x);
}

void dfs(int u,int fa,ll now)
{
    a[u]=now;
    for (int i=0;i<G[u].size();i++)
    {
        int v=G[u][i].first;
        ll w=G[u][i].second;
        if (a[v]==-1) dfs(v,u,now^w);
        else insert(now^a[v]^w);
    }
}

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    memset(a,-1,sizeof(a));
    for (int i=1;i<=m;i++)
    {
        int u,v;
        ll w;
        scanf("%d%d%lld",&u,&v,&w);
        G[u].push_back(make_pair(v,w));
        G[v].push_back(make_pair(u,w));
    }
    dfs(1,0,0);
    sort(base.begin(),base.end());
    ll ans=a[n];
    for (int i=base.size()-1;i>=0;i--) ans=max(ans,ans^base[i]);
    printf("%lld",ans);
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!