[XOR最小生成树 分治 Trie || Prim 堆] BNUOJ 52318 Be Friends
2016-12-23 16:20
375 查看
关于位运算生成树问题 尛焱轟在APIO上专门讲过 一些杂七杂八的东西
这个可以分治 显然对于最高位 为0的一团 为1的一团 那么只需要找最小的一条边连接 这个可以在其中一半枚举 另一半建成Trie在上面查询
然后分治到低一位
具体实现 对于一个排好序的序列 字典树每一个节点 对应序列上一个区间 可以记一个l r
当然还有乱搞的Prim
可以用堆存每个已经确定的点到未确定的点的最小边 然后每次加入最小的边 最小同样用Trie查询
复杂度我不是很清楚
不过还是没怎么搞清楚
这个可以分治 显然对于最高位 为0的一团 为1的一团 那么只需要找最小的一条边连接 这个可以在其中一半枚举 另一半建成Trie在上面查询然后分治到低一位
具体实现 对于一个排好序的序列 字典树每一个节点 对应序列上一个区间 可以记一个l r
#include<cstdio> #include<cstdlib> #include<algorithm> #include<queue> using namespace std; typedef long long ll; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=100005; const int K=31; int n,a ; int root,ncnt; int ls[N*(K+2)],rs[N*(K+2)],cnt[N*(K+2)],l[N*(K+2)],r[N*(K+2)]; int idx; inline void Ins(int &x,int num,int t){ if (!x) x=++ncnt,l[x]=idx; cnt[x]++; r[x]=idx; if (t) (num>>(t-1)&1)?Ins(rs[x],num,t-1):Ins(ls[x],num,t-1); } inline int Query(int x,int num,int t){ if (!t) return 0; if (num>>(t-1)&1) return rs[x]?Query(rs[x],num,t-1):Query(ls[x],num,t-1)+(1<<(t-1)); else return ls[x]?Query(ls[x],num,t-1):Query(rs[x],num,t-1)+(1<<(t-1)); } ll ans; inline void Solve(int x,int t){ if (!t) return; if (l[x]==r[x]) return; if (ls[x] && rs[x]){ ll minv=1LL<<60; for (int i=l[ls[x]];i<=r[ls[x]];i++) minv=min(minv,(1LL<<(t-1))+Query(rs[x],a[i],t-1)); ans+=minv; } if (ls[x]) Solve(ls[x],t-1); if (rs[x]) Solve(rs[x],t-1); } int main(){ freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); for (int i=1;i<=n;i++) read(a[i]); sort(a+1,a+n+1); n=unique(a+1,a+n+1)-a-1; root=++ncnt; for (int i=1;i<=n;i++) idx=i,Ins(root,a[i],32); Solve(root,32); printf("%lld\n",ans); return 0; }
当然还有乱搞的Prim
可以用堆存每个已经确定的点到未确定的点的最小边 然后每次加入最小的边 最小同样用Trie查询
复杂度我不是很清楚
#include<cstdio> #include<cstdlib> #include<algorithm> #include<queue> using namespace std; typedef long long ll; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=100005; const int K=31; int n,a ; int vst ; struct abcd{ int u,v; abcd(int u=0,int v=0):u(u),v(v) { } bool operator < (const abcd &B) const{ return (u^v)>(B.u^B.v); } }; inline int Bin(int x){ return lower_bound(a+1,a+n+1,x)-a; } int root,ncnt; int ls[N*(K+2)],rs[N*(K+2)],cnt[N*(K+2)]; inline void Ins(int &x,int num,int t){ if (!x) x=++ncnt; cnt[x]++; if (t) (num>>(t-1)&1)?Ins(rs[x],num,t-1):Ins(ls[x],num,t-1); } inline void Del(int &x,int num,int t){ if (t) (num>>(t-1)&1)?Del(rs[x],num,t-1):Del(ls[x],num,t-1); if (!(--cnt[x])) x=0; } inline int Query(int x,int num,int t){ if (!t) return 0; if (num>>(t-1)&1) return rs[x]?Query(rs[x],num,t-1)+(1<<(t-1)):Query(ls[x],num,t-1); else return ls[x]?Query(ls[x],num,t-1):Query(rs[x],num,t-1)+(1<<(t-1)); } priority_queue<abcd> Q; ll ans; int main(){ abcd tem; int u,v; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); for (int i=1;i<=n;i++) read(a[i]); sort(a+1,a+n+1); n=unique(a+1,a+n+1)-a-1; root=++ncnt; for (int i=2;i<=n;i++) Ins(root,a[i],32); Q.push(abcd(a[1],Query(root,a[1],32))); vst[1]=1; for (int i=2;i<=n;i++){ while (vst[Bin(Q.top().v)]){ tem=Q.top(); Q.pop(); if (root) Q.push(abcd(tem.u,Query(root,tem.u,32))); } tem=Q.top(); u=tem.u; v=tem.v; Q.pop(); Del(root,v,32); vst[Bin(v)]=1; ans+=u^v; if (root) Q.push(abcd(u,Query(root,u,32))); if (root) Q.push(abcd(v,Query(root,v,32))); } printf("%lld\n",ans); return 0; }
相关文章推荐
- [xor最小生成树 分治 字典树合并] BNUOJ52318 Be Friends
- [分治][Trie][prufer数列] 51Nod 1601 完全图的最小生成树计数
- BNUOJ 52318 Be Friends prim+Trie
- HDU 1233 <最小生成树prim><稠密图><可做模版>
- poj 1789 Truck History 最小生成树(prim)
- Prim(最小生成树)
- prim最小生成树算法题poj2485
- POJ1789 Truck History 【最小生成树Prim】
- 最小生成树之Prim的应用
- 普里姆(Prim)求最小生成树
- ZOJ 1372 Networking(Prim求最小生成树)
- 最小生成树算法(Prim和Kruskal)
- 图论总结 Dijkstra Tarjan 最小生成树 二分图 最短路 强连通分量 双连通分量 Bellman-Ford SPFA 二分图染色 Kruskal Prim 网络流 二分图匹配 Dinic
- 最小生成树 prim
- 最小生成树_Prim
- POJ 1258-Agri-Net(最小生成树prim)
- QS Network (最小生成树——prim方法)
- POJ1258 (最小生成树prim)
- 最小生成树之 prim & kruskal
- 8-06. 畅通工程之局部最小花费问题(35)(最小生成树_Prim)(ZJU_PAT)