• 洛谷P4551 最长异或路径


    传送门:https://www.luogu.org/problem/show?pid=4551

    在看这道题之前,我们应懂这道题怎么做:给定n个数和一个数m,求m和哪一个数的异或值最大。

    一种很不错的做法是将n个数按二进制从最高位到低位建立一个trie树,然后把m放在trie树上跑一遍。

    因为是从高位到低位存的,所以对于每一位,我们只要贪心让这一位的异或值得1。即如果m得当前位是1,就在trie树上找0;否则就找1.若能找到,ans的这一位就是1,否则是0.

    如果上述这道水题会了的话,这道题就不难想了。

    首先预处理每一个点到根节点的异或距离,为什么这么做呢,看下图

    比如点7到根节点的距离dis[7] = f ^ b ^ a,点6到根节点的距离dis[6] = c ^ a,则dis[7] ^ dis[6] = f ^ b ^ c ^ a ^ a = f ^ b ^ c,恰好为6到7的距离。

    因此我们就可以像上面这道题一样,将所有dis放到trie树里面,然后再让每一个dis[i]跑一遍trie树,最后结果取max即可。

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<iostream>
      6 #include<queue>
      7 #include<vector>
      8 #include<cctype>    //isdigit 
      9 using namespace std;
     10 typedef long long ll;
     11 #define enter printf("
    ")
     12 const int maxn = 1e5 + 5;
     13 const int INF = 0x3f3f3f3f;
     14 inline ll read() {
     15     ll ans = 0;
     16     char ch = getchar(), last = ' ';
     17     while(!isdigit(ch)) {
     18         last = ch;
     19         ch = getchar();
     20     }
     21     while(isdigit(ch)) {
     22         ans = ans * 10 + ch - '0';
     23         ch = getchar();
     24     }
     25     if(last == '-') ans = -ans;
     26     return ans;
     27 }
     28 inline void write(ll x) {
     29     if(x < 0) {
     30         putchar('-');
     31         x = -x;
     32     }
     33     if(x == 0) {
     34         putchar('0');
     35         return;
     36     }
     37     int q[100], N = 0;
     38     q[1] = 0;
     39     while(x) {
     40         q[++N] = x % 10;
     41         x /= 10;
     42     }
     43     while(N) {
     44         putchar('0' + q[N]);
     45         --N;
     46     }
     47 }
     48 
     49 int n;
     50 vector<int> v[maxn], c[maxn];
     51 int cost[maxn];
     52 bool vis[maxn];
     53 void bfs(int s) {                        //bfs预处理每一个点到根节点的距离 
     54     queue<int> q;
     55     q.push(s);
     56     vis[s] = 1;
     57     cost[s] = 0;
     58     while(!q.empty()) {
     59         int now = q.front();
     60         q.pop();
     61         for(int i = 0; i < (int)v[now].size(); ++i) {
     62             if(!vis[v[now][i]]) {
     63                 vis[v[now][i]] = 1;
     64                 cost[v[now][i]] = cost[now] ^ c[now][i];
     65                 q.push(v[now][i]);
     66             }
     67         }
     68     }
     69 }
     70 struct Trie {
     71     int ch[maxn * 35][2], tot;
     72     Trie() {
     73         memset(ch, 0, sizeof(ch));
     74         tot = 0;
     75     }
     76     void Insert(int x) {                //建树 
     77         int now = 0;
     78         for(int i = 30; i >= 0; --i) {
     79             int w = (x >> i) & 1;
     80             if(!ch[now][w]) ch[now][w] = ++tot;        
     81             now = ch[now][w];
     82         }
     83     }
     84     int query(int x) {
     85         int now = 0, ret = 0;
     86         for(int i = 30; i >= 0; --i) {
     87             int w = (x >> i) & 1;
     88             if(!ch[now][!w]) now = ch[now][w];
     89             else {
     90                 now = ch[now][!w];                //若和x这一位不同的边存在,就走这条边,同时ret的这一位标记成1 
     91                 ret += (1 << i);
     92             }
     93         }
     94         return ret;
     95     }
     96 } trie;
     97 
     98 int ans = 0;
     99 
    100 int main() {
    101     n = read();
    102     for(int i = 1; i < n; ++i) {
    103         int a = read(), b = read(), cost = read();
    104         v[a].push_back(b);
    105         c[a].push_back(cost);
    106         v[b].push_back(a);
    107         c[b].push_back(cost);
    108     }
    109     bfs(1);
    110     for(int i = 1; i <= n; ++i)
    111         trie.Insert(cost[i]);
    112     for(int i = 1; i <= n; ++i)
    113         ans = max(ans, trie.query(cost[i]));
    114     write(ans);
    115     enter;
    116     return 0;
    117 }
  • 相关阅读:
    UVALive 7752 Free Figurines (瞎搞)
    ifram的使用 左边是<a>链接 右边是对应网页嵌套的显示网页链接内容 和toggle的收放用法
    java.util.Collections.synchronizedSet()方法的使用
    hibernate的反向生成改懒加载的地方
    SSM的XML和WEB.XML的配置
    通过System获取java环境变量的路径
    Java:对象的强、软、弱和虚引用的区别
    Struts2方法调用的三种方式(有新的!调用方法的说明)
    静态代理,动态代理,Cglib代理详解
    spring自定义注解拦截器的配置
  • 原文地址:https://www.cnblogs.com/mrclr/p/9047311.html
Copyright © 2020-2023  润新知