无向图中,找1->n路径异或和最大(可以不是简单路径)

题:https://www.luogu.com.cn/problem/P4151

题意:无向图找1到n路径异或和最大;

分析:可以不是简单路径,所以可以走出去再回来,而走出去走回来如果是链的话就是0了,那么是简单环的话答案的贡献就可以加上这个简单环的异或和;

   所以我们可以把简单环的异或和扔到线性基里,然后考虑1到n的任意路径贡献为x;

   接着考虑在线性基中从大到小异或上当前贡献x会不会更大,那么就异或上;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
#define MP make_pair
const int M=60;
const int N=1e5+5;
ll dis[N],vis[N];
vector< pair<int,ll> >g[N];
struct LB{
    ll a[M+2];
    vector<ll>vec;
    void init(){
        for(int i=0;i<=M;i++) a[i]=0;
        vec.clear();
    }
    void Insert(ll x){
        for(int i=M;i>=0;i--){
            if(!(x&(1ll<<i))) continue;

            if(a[i]) x^=a[i];
            else{
                for(int j=0;j<i;j++) if(x&(1ll<<j)) x^=a[j];
                for(int j=i+1;j<=M;j++) if(a[j]&(1ll<<i)) a[j]^=x;

                a[i] = x;
                return ;
            }
        }
    }
    void getvec(){
        for(int i=0;i<=M;i++) if(a[i]) vec.pb(a[i]);
    }
    ll getdis(ll x){
        ll res=x;
        for(int i=vec.size()-1;i>=0;i--) {
            if((res^vec[i])>res) res^=vec[i];
        }
        return res;
    }
}lb;
void dfs(int u,ll sum){
    dis[u]=sum;
    vis[u]=1;
    for(auto it:g[u]){
        int v=it.first;
        ll w=it.second;
        if(vis[v]) lb.Insert(sum^w^dis[v]);
        else dfs(v,sum^w);
    }
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    lb.init();
    for(int u,v,i=1;i<=m;i++){
        ll w;
        scanf("%d%d%lld",&u,&v,&w);
        g[u].pb(MP(v,w));
        g[v].pb(MP(u,w));
    }
    dfs(1,0);
    lb.getvec();
    printf("%lld\n",lb.getdis(dis[n]));
    return 0;
}
View Code

 

posted @ 2020-10-12 23:09  starve_to_death  阅读(200)  评论(0编辑  收藏  举报