zoukankan      html  css  js  c++  java
  • 牛客多校五 B.Graph【最小异或生成树】

    题意:

      给定一棵无根树,可以添加边使之存在环,添加或删除都需要满足环上异或和为0,求最后的最小生成树

    做法:

      把树通过dfs处理异或和添加边变成一个无向完全图,在这张图上面跑Boruvka算法求最小生成树

      Boruvka算法可以解决需要对边之间进行一定处理后的最小生成树问题

    CODE

      1 #include <bits/stdc++.h>
      2 #define dbug(x) cout << #x << "=" << x << endl
      3 #define eps 1e-8
      4 #define pi acos(-1.0)
      5  
      6 using namespace std;
      7 typedef long long LL;
      8  
      9 const int inf = 0x3f3f3f3f;
     10  
     11 template<class T>inline void read(T &res)
     12 {
     13    char c;T flag=1;
     14    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
     15    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
     16 }
     17 
     18 const int maxn = 2e5 + 7;
     19 
     20 int n;
     21 int edge[maxn << 1], head[maxn << 1], nxt[maxn << 1], len[maxn << 1], cnt;
     22 vector<int> a;
     23 
     24 //01字典树
     25 struct Tire {
     26     int ch[maxn * 31][2], l[maxn * 31], r[maxn * 31];
     27     int sz[maxn * 31];
     28     int siz = 0;
     29     LL ans = 0;
     30     void insert(int num) {
     31         int u = 0;
     32         for ( int i = 29; i >= 0; --i ) {
     33             int id = (a[num] >> i) & 1;
     34             if(!ch[u][id]) {
     35                 ch[u][id] = ++siz;
     36                 memset(ch[siz], 0, sizeof(siz));
     37                 l[siz] = r[siz] = num;
     38             }
     39             u = ch[u][id], ++sz[u], l[u] = min(l[u], num), r[u] = max(r[u], num);
     40         }
     41     }
     42 
     43     int find(int u, int dep, int val) {
     44         if(!dep || l[u] == r[u]) {
     45             return a[l[u]];
     46         }
     47         int id = (val >> (dep - 1)) & 1;
     48         if(ch[u][id]) {
     49             return find(ch[u][id], dep - 1, val);
     50         }
     51         else {
     52             return find(ch[u][id ^ 1], dep - 1, val);
     53         }
     54     }
     55 
     56     void dfs(int u, int dep) {
     57         if(!dep) {
     58             return;
     59         }
     60         int ls = ch[u][0], rs = ch[u][1];
     61         if(ls && rs) {
     62             LL res = 1e17;
     63             if(sz[ls] <= sz[rs]) {
     64                 for ( int i = l[ls]; i <= r[ls]; ++i ) {
     65                     res = min(res, 1ll * a[i] ^ find(rs, dep - 1, a[i]));
     66                 }
     67             }
     68             else {
     69                 for ( int i = l[rs]; i <= r[rs]; ++i ) {
     70                     res = min(res, 1ll * a[i] ^ find(ls, dep - 1, a[i]));
     71                 }
     72             }
     73             ans += res;
     74         }
     75         if(sz[ls] > 1) {
     76             dfs(ls, dep - 1);
     77         }
     78         if(sz[rs] > 1) {
     79             dfs(rs, dep - 1);
     80         }
     81     }
     82 
     83     void init() {
     84         memset(sz, 0, sizeof(sz));
     85         memset(ch[0], 0, sizeof(ch[0]));
     86         siz = ans = 0;
     87     }
     88 } trie;
     89 //01字典树
     90 
     91 void BuildGraph(int u, int v, int w) {
     92     ++cnt;
     93     edge[cnt] = v;
     94     nxt[cnt] = head[u];
     95     head[u] = cnt;
     96     len[cnt] = w;
     97 }
     98 
     99 void dfs(int u, int fa, int val) {
    100     a.push_back(val);
    101     for ( int i = head[u]; i; i = nxt[i] ) {
    102         int v = edge[i];
    103         if(v == fa) {
    104             continue;
    105         }
    106         dfs(v, u, val ^ len[i]);
    107     }
    108 }
    109 int main() 
    110 {
    111     read(n);
    112     int u, v, w;
    113     for ( int i = 1; i <= n - 1; ++i ) {
    114         read(u); read(v); read(w);
    115         ++u, ++v;
    116         BuildGraph(u, v, w);
    117         BuildGraph(v, u, w);
    118     }
    119     dfs(1, 0, 0);
    120     sort(a.begin(), a.end());
    121     a.erase(unique(a.begin(), a.end()), a.end());
    122     trie.init();
    123     int len = a.size();
    124     for ( int i = 0; i <= len - 1; ++i ) {
    125         trie.insert(i);
    126     }
    127     trie.dfs(0, 30);
    128     cout << trie.ans << endl;
    129     return 0;
    130 }
    View Code
  • 相关阅读:
    OpenJDK源码研究笔记(十二):JDBC中的元数据,数据库元数据(DatabaseMetaData),参数元数据(ParameterMetaData),结果集元数据(ResultSetMetaDa
    Java实现 LeetCode 257 二叉树的所有路径
    Java实现 LeetCode 257 二叉树的所有路径
    Java实现 LeetCode 257 二叉树的所有路径
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 241 为运算表达式设计优先级
    Java实现 LeetCode 241 为运算表达式设计优先级
    Java实现 LeetCode 241 为运算表达式设计优先级
  • 原文地址:https://www.cnblogs.com/orangeko/p/13409812.html
Copyright © 2011-2022 走看看