题目链接:

https://acm.bnu.edu.cn/v3/problem_show.php?pid=52318

B. Be Friends

Case Time Limit: 2500ms
Memory Limit: 524288KB

题意

给你n个点,每个点有一个权值a[i],对于两个点u,v,他们之间的边的权值为a[u]^a[v],现在让你求一颗最小生成树。

题解

Trie可以求离点u最近的点v(既u^v最小),利用这一点,我们用prim来求最小生成树, 可以用优先队列维护一下离我们已经扩展的集合的最近的点,最近的点是可以用Trie处理出来的。

代码

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxnode=2e6+10;
const int maxn=1e5+10; struct Node {
int u,v;
bool operator < (const Node& tmp) const {
return (u^v)>(tmp.u^tmp.v);
}
Node(int u,int v):u(u),v(v) {}
}; ///ch[0]为超级节点,不止是代表第一个点,很多点会连到上面,所以它的cntv必须为0,代表着终结。
struct Trie {
int ch[maxnode][2];
//cntv统计子树下的单词节点个数,val记录单词节点
int cntv[maxnode],val[maxnode];
int sz,cnt;
Trie() {
sz=1;
clr(ch[0],0);
cnt=0;
} void insert(int x) {
cnt++;
int arr[44]= {0},tot=0,tmp=x;
while(tmp) {
arr[++tot]=tmp&1;
tmp>>=1;
} int u=0;
for(int i=33; i>=1; i--) {
int c=arr[i];
if(!ch[u][c]) {
clr(ch[sz],0);
cntv[sz]=0;
val[sz]=-10086;
ch[u][c]=sz++;
}
u=ch[u][c];
cntv[u]++;
}
val[u]=x;
} int query(int x) {
if(cnt==0) return -1; int arr[44]= {0},tot=0,tmp=x;
while(tmp) {
arr[++tot]=tmp&1;
tmp>>=1;
} int u=0;
for(int i=33; i>=1; i--) {
int c=arr[i];
if(cntv[ch[u][c]]) {
u=ch[u][c];
} else {
u=ch[u][c^1];
}
}
return val[u];
} void del(int x) {
cnt--;
int arr[44]= {0},tot=0,tmp=x;
while(tmp) {
arr[++tot]=tmp&1;
tmp>>=1;
} int u=0;
for(int i=33; i>=1; i--) {
int c=arr[i];
cntv[ch[u][c]]--;
u=ch[u][c];
}
} } trie; int arr[maxn],n;
map<int,bool> mp; int main() {
scf("%d",&n);
for(int i=1; i<=n; i++) scf("%d",&arr[i]);
sort(arr+1,arr+n+1);
n=unique(arr+1,arr+n+1)-arr-1; for(int i=2; i<=n; i++) {
trie.insert(arr[i]);
} priority_queue<Node> pq; if(n==1) {
prf("0\n");
return 0;
} ///prim求最小生成树
int tmp=trie.query(arr[1]);
pq.push(Node(arr[1],tmp));
mp[arr[1]]=true; LL ans=0;
for(int i=2; i<=n; i++) { while(mp[pq.top().v]){
int u=pq.top().u;
pq.pop();
int v=trie.query(u);
if(v>=0){
// prf("f(%d,%d)\n",u,v);
pq.push(Node(u,v));
}
} int u=pq.top().u,v=pq.top().v;
pq.pop();
trie.del(v);
mp[v]=true;
ans+=u^v; int u2=trie.query(u);
if(u2>=0){
pq.push(Node(u,u2));
} int v2=trie.query(v);
if(v2>=0){
pq.push(Node(v,v2));
}
} prf("%lld\n",ans); return 0;
}

BNUOJ 52318 Be Friends prim+Trie的更多相关文章

  1. bnuoj 25662 A Famous Grid (构图+BFS)

    http://www.bnuoj.com/bnuoj/problem_show.php?pid=25662 #include <iostream> #include <stdio.h ...

  2. 【CF888G】Xor-MST(最小生成树,Trie树)

    [CF888G]Xor-MST(最小生成树,Trie树) 题面 CF 洛谷 题解 利用\(Kruskal\)或者\(Prim\)算法都很不好计算. 然而我们还有一个叫啥来着?\(B\)啥啥的算法,就叫 ...

  3. BNUOJ 12756 Social Holidaying(二分匹配)

    题目链接:http://www.bnuoj.com/bnuoj/problem_show.php?pid=12756 Social Holidaying Time Limit: 3000ms Memo ...

  4. 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

    图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...

  5. 基于trie树做一个ac自动机

    基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...

  6. 基于trie树的具有联想功能的文本编辑器

    之前的软件设计与开发实践课程中,自己构思的大作业题目.做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改.github:https://github.com/chu ...

  7. [LeetCode] Implement Trie (Prefix Tree) 实现字典树(前缀树)

    Implement a trie with insert, search, and startsWith methods. Note:You may assume that all inputs ar ...

  8. hihocoder-1014 Trie树

    hihocoder 1014 : Trie树 link: https://hihocoder.com/problemset/problem/1014 题意: 实现Trie树,实现对单词的快速统计. # ...

  9. 【BZOJ-2938】病毒 Trie图 + 拓扑排序

    2938: [Poi2000]病毒 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 609  Solved: 318[Submit][Status][Di ...

随机推荐

  1. hadoop日常维护之问题解决01

    执行hadoop任务遇到的问题: Caused by: org.apache.hadoop.ipc.RemoteException(java.io.IOException): File /user/h ...

  2. webBrowser.Document.Cookie取不到HttpOnly的Cookie,取Cookie不完整

    在做数据采集时,有些网站需要输入验证码,但各网站验证码都不同,不可能有完美的识别验证码的代码,所以我也没去研究,我所采取的方案是:在winform里通过WebBrowser调用网页先手动登录系统,然后 ...

  3. This assembly may have been downloaded from the Web. ......

    错误消息例如: Error 6 Could not load the assembly file:///D:\me\Projects\DLL\Newtonsoft.Json\Portable40\Ne ...

  4. 26-[Boostrap]-全局css样式,组件,控件

    1.全局CSS样式 https://v3.bootcss.com/css/ <!DOCTYPE html> <html lang="zh-CN"> < ...

  5. 【BZOJ1070】[SCOI2007]修车

    [BZOJ1070][SCOI2007]修车 题面 以后要多写题面flag 题目描述 同一时刻有\(N\)位车主带着他们的爱车来到了汽车维修中心.维修中心共有\(M\)位技术人员,不同的技术人员对不同 ...

  6. 洛咕 P2463 [SDOI2008]Sandy的卡片

    哈希水过. 首先这是一段delta相同的序列,按照套路差分一下,b[i]=a[i]-a[i-1],然后就是这些序列的最长公共子段 由于数据范围很小,就可以二分,枚举第一个序列的子段然后每个子序列暴力c ...

  7. Object C学习笔记1-基本数据类型说明

    Objective-C数据类型可以分为:基本数据类型.对象类型和id类型.基本数据类型有:int.float.double和char类型.对象类型就是类或协议所声明的指针类型,例如:NSAutorel ...

  8. Mac电脑如何快速下载YouTube视频

    如果你想下载一些教育类的视频资源,或者是一些学习的教程,那么YouTube是一个很好的视频资源平台.YouTube上面各种各样的资源都有,而且质量都很有保证,尤其是那些订阅量很多的人.可惜的是,You ...

  9. python描述符详解

    1描述符: 描述符是指将某种特殊类型的类的实例支配给另外一个类的属性. 对于特殊类型必须实现以下三个方法中至少一个方法:    def __get__(self,instance,owner): -用 ...

  10. 《杜增强讲Unity之Tanks坦克大战》2-场景设置

    2  场景设置 2.1 本节效果预览   2.2 项目目录设置 点击Project面板的Create按钮,在根目录下面新建wm文件夹   Wm文件夹用于存放我们自己生成的Prefab和脚本等其他资源, ...