zoukankan      html  css  js  c++  java
  • 2115: [Wc2011] Xor (线性基+dfs)

    2115: [Wc2011] Xor

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 5714  Solved: 2420

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

    Description:

    Input:

    第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目。 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 Di的无向边。 图中可能有重边或自环。

    Output:

    仅包含一个整数,表示最大的XOR和(十进制结果),注意输出后加换行回车。

    Sample Input:

    1 2 2
    1 3 2
    2 4 1
    2 5 1
    4 5 3
    5 3 4
    4 3 2

    Sample Output:

    6

    Hint:

    题解:

    我感觉这个题是很巧妙的一个题,直接dfs搜路径是显然行不通的。

    其实通过观察可以发现,最终的最大异或值所走的路径,一定是一条路径加上若干环形成的。

    那么我们考虑通过一次dfs将所有环的异或和求出来,然后随便选择一条路径作为我们的起始路径,这里有两种情况:

    1.环没在路径上,那么此时我们走的时候就是通过若干点到那个环,然后又从那若干点回来,最终对答案有贡献的就只有环的异或和;

    2.环在路径上,此时我们将这个环与原路径异或一下,那么原路径与环重叠部分就会抵消,然后会形成一条新的更优的路径。

    那么此时如果我们将环与路径的最大异或值找出来,最终也是一条路径和若干环,这时就考虑利用线性基来求异或最大值。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 100005,M = 100005;
    int n,m,tot,num;
    int head[N],vis[N];
    ll x[N],cir[N<<1];
    struct Edge{
        int u,v,next;
        ll w;
    }e[M<<1];
    void adde(int u,int v,ll w){
        e[tot].v=v;e[tot].next=head[u];e[tot].w=w;head[u]=tot++;
    }
    void dfs(int u,int fa){
        vis[u]=1;
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(v==fa) continue ;
            if(!vis[v]){
                x[v]=x[u]^e[i].w;
                dfs(v,u);
            }else{
                cir[++num]=x[v]^x[u]^e[i].w;
            }
        }
    }
    ll p[65];
    ll ans;
    void xor_base(){
        for(int i=1;i<=num;i++){
            for(ll j=62;j>=0;j--){
                if((1LL<<j)&cir[i]){
                    if(!p[j]){
                        p[j]=cir[i];
                        break;
                    }
                    cir[i]^=p[j];
                }
            }
        }
    }
    int main(){
        ios::sync_with_stdio(false);cin.tie(0);
        cin>>n>>m;
        memset(head,-1,sizeof(head));tot=num=0;
        for(int i=1;i<=m;i++){
            int u,v;ll w;
            cin>>u>>v>>w;
            adde(u,v,w);adde(v,u,w);
        }
        dfs(1,-1);
        ans=x[n];
        xor_base();
        for(int i=62;i>=0;i--){
            ans=max(ans,ans^p[i]);
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    Study Plan The TwentySecond Day
    Study Plan The Nineteenth Day
    Study Plan The TwentySeventh Day
    Study Plan The Twentieth Day
    Study Plan The TwentyFirst Day
    python实现进程的三种方式及其区别
    yum makecache
    JSONPath 表达式的使用
    oracle执行cmd的实现方法
    php daodb插入、更新与删除数据
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10422151.html
Copyright © 2011-2022 走看看