zoukankan      html  css  js  c++  java
  • 洛谷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 }
  • 相关阅读:
    训练总结
    图论--最短路--SPFA模板(能过题,真没错的模板)
    图论--最短路-- Dijkstra模板(目前见到的最好用的)
    The 2019 Asia Nanchang First Round Online Programming Contest B Fire-Fighting Hero(阅读理解)
    关于RMQ问题的四种解法
    The Preliminary Contest for ICPC Asia Xuzhou 2019 徐州网络赛 K题 center
    The Preliminary Contest for ICPC Asia Xuzhou 2019 徐州网络赛 XKC's basketball team
    The Preliminary Contest for ICPC Asia Xuzhou 2019 徐州网络赛 D Carneginon
    ZOJ 3607 Lazier Salesgirl (枚举)
    ZOJ 3605 Find the Marble(dp)
  • 原文地址:https://www.cnblogs.com/mrclr/p/9047311.html
Copyright © 2011-2022 走看看