zoukankan      html  css  js  c++  java
  • bzoj 2115 路径xor和最大值

    首先我们可以将这张图转化为一棵树,其中可能有好多环,肯定是从1走到N,其中可能经过好多环,

    因为我们不走N在的一支,最后还是会走回来,因为a xor b xor b=a,所以相当于没走,就是走了个环,

    那么我们这个题可以转化成有若干个环的值,还有1-n的值,在环中全任意个,xor起来再xor 1-n的,

    使最后最大。

    求环的时候我们可以记下每个点的一个值,代表从1到这个点的路径值xor,用size表示(我英语不好。。。)

    那么我们做一遍dfs,如果X访问到已经走过的点P了,那么就出现了环,环中的值就是SIZE[p] xor size[x] xor len[q]

    这样我们就得到了环的值。

    这里的环不一定是所有的环,可能有些环得不到,但是通过已知的值可以xor出来

    那么问题就被成功的转化了,这时我们需要了解一些性质

    假设集合A,其中我们将ai替换成ai xor a[j] i<>j,那么得到的新集合,这个集合中元素能xor出的值于集合A相同

    那么我们就用类似于高斯消元的方法,将每个数(环的值)弄成二进制来看(只是来看),从高位找起,如果所有二进制

    最高位是i,那么找到一个最高位是I的元素,用a[i] xor a[j] 替换所有最高位是I的元素j,那么这个集合可以看成是不变的

    (能得出的值不变),并且将I元素移出A集合,直到集合中没有数为止

    那么我们可以得到一些移出集合的值(也叫做第I位的基),我们从最高位开始贪心,设1-n的xor是ans,那么我们看ans的I位

    是不是1,如果不是那么就xor上第I位的基,最后输出ans就行了

    /**************************************************************
        Problem: 2115
        User: BLADEVIL
        Language: Pascal
        Result: Accepted
        Time:1520 ms
        Memory:8256 kb
    ****************************************************************/
     
    //By BLADEVIL
    var
        n, m                            :int64; 
        pre, other                      :array[0..200010] of int64; 
        len                             :array[0..200010] of int64; 
        last                            :array[0..50010] of int64; 
        l                               :int64; 
        a                               :array[0..200010] of int64; 
        flag                            :array[0..200010] of boolean; 
        size                            :array[0..50010] of int64; 
        tot                             :int64; 
        ans                             :int64;
         
    procedure swap(var a,b:int64);
    var
        c                               :int64;
    begin
        c:=a; a:=b; b:=c;
    end;    
     
    procedure connect(x,y:int64;z:int64); 
    begin
        inc(l); 
        pre[l]:=last[x]; 
        last[x]:=l; 
        other[l]:=y; 
        len[l]:=z; 
    end; 
     
    procedure dfs(x:int64); 
    var
        q, p                            :int64; 
    begin 
        flag[x]:=true;
        q:=last[x]; 
        while q<>0 do
        begin
            p:=other[q]; 
            if not flag[p] then
            begin
                size[p]:=size[x] xor len[q]; 
                dfs(p); 
            end else
            begin
                inc(tot); 
                a[tot]:=size[x] xor len[q] xor size[p]; 
                if a[tot]=0 then dec(tot); 
            end; 
            q:=pre[q]; 
        end; 
    end; 
     
    procedure init; 
    var
        i                               :longint; 
        x, y                            :int64; 
        z                               :int64;
    begin
        read(n,m); 
        for i:=1 to m do
        begin
            read(x,y,z); 
            connect(x,y,z); 
            connect(y,x,z); 
        end; 
        dfs(1); 
    end; 
        
    procedure qs(low,high:int64);
    var
        i, j                            :longint;
        xx                              :int64;
    begin
        i:=low; j:=high; xx:=a[(i+j) div 2];
        while i<j do
        begin
            while a[i]>xx do inc(i);
            while a[j]<xx do dec(j);
            if i<=j then
            begin
                swap(a[i],a[j]);
                inc(i); dec(j);
            end;
        end;
        if i<high then qs(i,high);
        if j>low then qs(low,j);
    end;
        
    procedure main;
    var
        i, j, k                         :longint;
        cur                             :int64;
         
    begin
        fillchar(flag,sizeof(flag),false);
        cur:=1<<62;
        for i:=0 to 62 do
        begin
            for j:=1 to tot do
            if not flag[j] then
                if a[j] and cur=cur then
                begin
                    flag[j]:=true;
                    for k:=1 to tot do
                        if (not flag[k]) and (a[k] and cur=cur) then
                            a[k]:=a[k] xor a[j];
                    break;
                end;
            cur:=cur>>1;
        end;
        qs(1,tot);
        ans:=size[n];
        for i:=1 to tot do
        begin
            if a[i]=0 then break;
            if ans xor a[i]>ans then ans:=ans xor a[i];
        end;
        writeln(ans);
    end;
        
    begin
        init; 
        main;
    end.
  • 相关阅读:
    pcs7 opc 连接问题
    nuget 多个程序引用同一个库时,当个这个库更新时,引用的程序都要跟新,否则会在运行时出错
    nuget update FileConflictAction
    a
    C#版本
    .NET Framework版本与CLR版本之间的关系
    c# 将一种数组类型转成另一种数组类型
    tfs 清除缓存,在需要时
    java枚举和仿枚举
    java反射的用法
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3484486.html
Copyright © 2011-2022 走看看