zoukankan      html  css  js  c++  java
  • bzoj2115 [Wc2011] Xor

    Description

    Input

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

    Output

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

    Sample Input

    5 7
    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

    正解:线性基。

    又是一道鬼畜的线性基神题。。这是我做的第二道WC的题,也可能将会是我做的代码量最短的WC题。。

    我们考虑如何得到答案,首先所有的环都是可以经过的。这是为什么呢?

    假设我们从1号点开始走,走到一个环的起点,然后我们经过这个环以后回到了环的起点,这时我们可以直接回到起点。这样,除了环上的路径,其他的路径都被抵消了。那么我们就只选了了这个环,也就是说,任意一个环都是可以选的。

    然后我们先把所有的环都选出来,选入线性基中,再选出任意一条从1到n的路径,作为初始ans。初始ans异或线性基的最大值就是我们求的答案。为什么任意选一条路径也是可行的呢?

    我们选了一条路径以后,如果存在一条更优的路径,那么这两条路径肯定是构成一个环的,会被选入线性基中。那么我们再用初始的ans异或一下这个环,我们就会发现,初始的ans被抵消了,二更优的那条路径留了下来。所以,我们选一个任意的初始ans是可行的。

    于是这道题的实现就很明显了。先找出所有环,构成线性基,然后找出初始ans。这两步显然是可以dfs一遍一起搞的。然后用ans去异或线性基。从高位开始往低位异或。如果当前ans异或这一位的数能使ans变大,那么就异或。最终得到的ans就是我们要求的答案。

    所以根据这题,我们还可以得到一个结论:任意一条1到n的路径的异或和,都可以由任意一条1到n的路径的异或和和一些环的异或和来组合得到。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <complex>
     5 #include <cstring>
     6 #include <cstdlib>
     7 #include <cstdio>
     8 #include <vector>
     9 #include <cmath>
    10 #include <queue>
    11 #include <stack>
    12 #include <map>
    13 #include <set>
    14 #define inf (1<<30)
    15 #define M (100010)
    16 #define N (50010)
    17 #define il inline
    18 #define RG register
    19 #define ll long long
    20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    21 
    22 using namespace std;
    23 
    24 struct edge{ ll nt,to,dis; }g[2*M];
    25 
    26 ll a[4*M],head[N],vis[N],d[N],p[65],n,m,num,cnt,ans;
    27                    
    28 il ll gi(){
    29     RG ll x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    30     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
    31 }
    32 
    33 il void insert(RG ll from,RG ll to,RG ll dis){ g[++num]=(edge){head[from],to,dis},head[from]=num; return; }
    34 
    35 il void dfs(RG ll x){
    36     vis[x]=1;
    37     for (RG ll i=head[x],v=g[i].to;i;i=g[i].nt,v=g[i].to){
    38     if (!vis[v]) d[v]=d[x]^g[i].dis,dfs(v);
    39     else a[++cnt]=d[v]^d[x]^g[i].dis;
    40     }
    41     return;
    42 }
    43 
    44 il void add(RG ll x){
    45     for (RG ll i=62;i>=0;--i)
    46     if (x>>i&1){
    47         if (!p[i]){ p[i]=x; break; }
    48         x^=p[i];
    49     }
    50     return;
    51 }
    52 
    53 il ll getmax(RG ll x){ RG ll res=x; for (RG ll i=62;i>=0;--i) if (res<(res^p[i])) res^=p[i]; return res; }
    54 
    55 il void work(){
    56     n=gi(),m=gi(); for (RG ll i=1,u,v,w;i<=m;++i) u=gi(),v=gi(),w=gi(),insert(u,v,w),insert(v,u,w);
    57     dfs(1); for (RG ll i=1;i<=cnt;++i) add(a[i]); ans=getmax(d[n]); printf("%lld
    ",ans); return;
    58 }
    59 
    60 int main(){
    61     File("xor");
    62     work();
    63     return 0;
    64 }
  • 相关阅读:
    第六周作业
    2019第四周作业(基础作业+挑战作业)
    第三周作业
    2019第二周基础作业
    求最大值及下标值
    查找整数
    学期总结
    打印沙漏
    币值转换
    远程连接centos7的mysql5.7+ 更改iptables方法
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6547135.html
Copyright © 2011-2022 走看看