zoukankan      html  css  js  c++  java
  • [WC 2011]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

    题解

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

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

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

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

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

    补充谈谈对取出环的异或值的理解:

    我们记$d[u]$为从根节点,到$u$节点这条路径上的$xor$和,那么假设我们$dfs$拓展路径的时候,我们找到了以前一个访问过的点$v$,

    那么这里就构成了一个环,且由于是$dfs$实现的,很容易知道$d[u]=d[v]⊕w_1⊕w_2⊕...$,$w$为边权。

    我们记我们插入线性基的元素(环上的$xor$和)为$x$,$x=w_1⊕w_2⊕...⊕w_i$,

    因为我们知道$a⊕a=0$,那么$x=d[u]⊕d[u]⊕w_1⊕w_2⊕...⊕w_i$$=d[u]⊕d[v]⊕w_i$($w_i$为$u->v$的边权)

     1 //It is made by Awson on 2017.9.21
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime> 
     6 #include <queue>
     7 #include <stack>
     8 #include <string>
     9 #include <cstdio>
    10 #include <vector>
    11 #include <cstdlib>
    12 #include <cstring>
    13 #include <iostream>
    14 #include <algorithm>
    15 #define Min(a, b) ((a) < (b) ? (a) : (b))
    16 #define Max(a, b) ((a) > (b) ? (a) : (b))
    17 #define LL long long
    18 using namespace std;
    19 const int N = 50000;
    20 const int M = 100000;
    21 LL st[64];
    22 
    23 int n, m, u, v;
    24 LL c;
    25 struct tt {
    26     int to, next;
    27     LL cost;
    28 }edge[2*M+5];
    29 int path[N+5], top;
    30 LL d[N+5];
    31 LL p[64];
    32 bool vis[N+5];
    33 
    34 LL getmax(LL x) {
    35     for (int i = 62; i >= 0; i--)
    36         if ((x^p[i]) > x)
    37             x ^= p[i];
    38     return x;
    39 }
    40 void insert(LL x) {
    41     for (int i = 62; i >= 0; i--)
    42         if (x&st[i]) {
    43             if (!p[i]) {
    44                 p[i] = x;
    45                 break;
    46             }
    47             x ^= p[i];
    48         }
    49 }
    50 void add(int u, int v, LL c) {
    51     edge[++top].to = v;
    52     edge[top].cost = c;
    53     edge[top].next = path[u];
    54     path[u] = top;
    55 }
    56 void dfs(int u) {
    57     vis[u] = 1;
    58     for (int i = path[u]; i; i = edge[i].next) {
    59         if (vis[edge[i].to]) insert(d[u]^d[edge[i].to]^edge[i].cost);
    60         else {
    61             d[edge[i].to] = d[u]^edge[i].cost;
    62             dfs(edge[i].to);
    63         }
    64     }
    65 }
    66 void work() {
    67     st[0] = 1;
    68     for (int i = 1; i < 63; i++) st[i] = st[i-1]<<1;
    69     for (int i = 1; i <= m; i++) {
    70         scanf("%d%d%lld", &u, &v, &c);
    71         add(u, v, c); add(v, u, c);
    72     }
    73     dfs(1);
    74     LL ans = getmax(d[n]);
    75     printf("%lld
    ", ans);
    76 }
    77 int main() {
    78     while (~scanf("%d%d", &n, &m))
    79         work();
    80     return 0; 
    81 }
  • 相关阅读:
    点击区域外隐藏该区域,event.stopPropagation()
    PHP 笔记一(systax/variables/echo/print/Data Type)
    <hr> 的18种样式
    CSS 设置背景透明度,不影响子元素
    console.dir() 与 console.log() 区别
    JS 鼠标滚轮事件(mousewheel/DOMMouseScroll)
    HTML 字符图案
    CSS 样式优先级
    替换元素和不可替换元素,块级元素和行内元素
    CSS3 笔记五(Buttons)
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7568739.html
Copyright © 2011-2022 走看看