1. 程式人生 > >[XOR最小生成樹 分治 Trie || Prim 堆] BNUOJ 52318 Be Friends

[XOR最小生成樹 分治 Trie || Prim 堆] BNUOJ 52318 Be Friends

#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[N];
int vst[N];

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小生成樹 分治 Trie || Prim ] BNUOJ 52318 Be Friends

#include<cstdio> #include<cstdlib> #include<algorithm> #include<queue> using namespace std; typedef long long ll; inline char nc()

無向帶權圖的小生成樹算法——Prim及Kruskal算法思路

下一個 必須 循環 算法與數據結構 最小值 邊集 當前 知識 所有 邊賦以權值的圖稱為網或帶權圖,帶權圖的生成樹也是帶權的,生成樹T各邊的權值總和稱為該樹的權。 最小生成樹(MST):權值最小的生成樹。 生成樹和最小生成樹的應用:要連通n個城市需要n-1條邊線路

圖之小生成樹 Kruskal演算法 Prim演算法

一.實際問題 最小生成樹一般應用在網(帶權的圖)問題中,實際問題一般比如:   假設要在n個城市間建立通訊聯絡網,則聯通n個城市只需要n-1條線路,但是每兩個城市間都可以建設路線,而且城市與城市間建設代價是不同的,這就需要我們考慮一種經濟的聯絡方式。 將問

小生成樹詳解 prim+ kruskal程式碼模板

最小生成樹概念: 一個有 n 個結點的連通圖的生成樹是原圖的極小連通子圖,且包含原圖中的所有 n 個結點,並且有保持圖連通的最少的邊。 最小生成樹可以用kruskal(克魯斯卡爾)演算法或prim(普里姆)演算法求出。最小生成樹其實是最小權重生成樹的簡稱。 prim: 概念:普里姆演算法(Prim演算法),

小生成樹MST(Prim/Kruskal模版)

生成樹:如果連通圖G的一個子圖是一棵包含G的所有頂點的樹,則該子圖稱為G的生成樹。生成樹不唯一,不同起點遍歷所得生成樹不同。 最小生成樹:邊權最小的生成樹。 最小邊原則:圖中權值最小的邊(如果唯一的話)一定在最小生成樹上。 唯一性:一棵生成樹上,如果各邊的

小生成樹構造演算法--Prim演算法,Kruskal演算法(C語言)

最小生成樹 最小生成樹(minimum spanning tree)是由n個頂點,n-1條邊,將一個連通圖連線起來,且使權值最小的結構。 最小生成樹可以用Prim(普里姆)演算法或kruskal(克魯斯卡爾)演算法求出。 我們將以下面的帶權連通圖為例講解這

每日一省之————加權無向圖的小生成樹演算法(Prim/Kruskal演算法)

1.帶權重的邊的資料結構 /** * 該類物件可以表示圖中的一條邊 * @author lhever 2017年2月19日 下午5:10:49 * @version v1.0 */ public class Edge implements Com

P3366 【模板】小生成樹優化prim

生成 operator prior 鄰接表 %d inline pac ont truct 堆優化prim 復雜度大概O(nlogn) #include<cstdio> #include<cstring> #include<queu

圖論——小生成樹prim+鄰接表+優化

pop turn str 第一個元素 for prior ace 最小生成樹 \n 今天學長對比了最小生成樹最快速的求法不管是稠密圖還是稀疏圖,prim+鄰接表+堆優化都能得到一個很不錯的速度,所以參考學長的代碼打出了下列代碼,make_pair還不是很會,大體理解的意思是

小生成樹(二)--prim演算法實現以及優化

一、最小生成樹---prim演算法實現 思想: 1、從任意一個頂點開始構造生成樹,假設就從1號頂點吧, 首先將頂點1加入生成樹中,用一個一維陣列book來標記 哪些頂點已經加入了生成樹。  2、用陣列dis記錄生成樹到各個頂點的距離,最初生成樹中之後1號 頂點,有直連邊時,

hiho一下 第二十八週 小生成樹三·優化的Prim演算法

描述 回到兩個星期之前,在成功的使用Kruscal演算法解決了問題之後,小Ho產生了一個疑問,究竟這樣的演算法在稀疏圖上比Prim優化之處在哪裡呢? 提示:沒有無緣無故的優化! 輸入 每個測試點(輸入檔案)有且僅有一組測試資料。 在一組測試資料中: 第1行為2個整數N、M,表示小Hi擁有的城市數量和小H

#1109 : 小生成樹三·優化的Prim演算法

時間限制:10000ms 單點時限:1000ms 記憶體限制:256MB 描述 回到兩個星期之前,在成功的使用Kruscal演算法解決了問題之後,小Ho產生了一個疑問,究竟這樣的演算法在稀疏圖上比Prim優化之處在哪裡呢? 提示:沒有無緣無故的優化! 輸入 每個測

Prim演算法實現小生成樹(圖模型+小根)

Prim演算法實現最小生成樹的思想是:在圖中取一個頂點為起始點,找出其鄰接的所有頂點,將該點和鄰接的頂點和邊的權值一一壓入小根堆中,接著從小根堆中退出小根堆的根,將沒訪問過的兩個頂點及其關聯邊的權值插入到最小生成樹中,以此類推,總共需要迴圈n-1次。 小根堆模組: int

hiho 29 小生成樹三·優化的Prim演算法

問題描述 最小生成樹演算法,在稀疏圖時,Kruscal複雜度更低,我們可以使用堆優化的prim演算法達到與Kruscal一樣的複雜度。 Prim演算法本身的時間複雜度是O(N^2)的,而在這個演算法中,使用了堆來維護所有的邊,運算元一共是O(M)級別的,所以

小生成樹----prim演算法的優化

用鄰接表+優先佇列可以實現對prim演算法的堆優化 prim的思想還是沒有改變,還是從任意一個點開始選擇,找出這個點連線的所有的邊,然後找出最短的,選中這條邊加入到生成樹中,列舉每一個樹頂點到每一個費數頂點的所有的邊,然後找最短的邊加入到生成樹,一直加邊n-1

小生成樹演算法——Kruskal演算法、Prim演算法、優化的Prim演算法

什麼叫最小生成樹? 已知一個無向連通圖,那麼這個圖的最小生成樹是該圖的一個子圖,且這個子圖是一棵樹且把圖中所有節點連線到一起了。一個圖可能擁有多個生成樹。一個帶權重的無向連通圖的最小生成樹(minimum spanning tree),它的權重和是小於等於其他

poj1861 小生成樹 prim &amp; kruskal

模板 bool content bre 水題 esp algorithm puts class // poj1861 最小生成樹 prim & kruskal // // 一個水題,為的僅僅是回味一下模板。日後好有個照顧不是 #include

HDU2489 Minimal Ratio Tree 【DFS】+【小生成樹Prim

mini note 推斷 sym hash %d ted n) lin Minimal Ratio Tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot

HDU 2489 Minimal Ratio Tree (dfs+Prim小生成樹)

tracking mode pid cas cond multi ima ces bold 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2489 Problem Description For a tree,

Prim算法:小生成樹---貪心算法的實現

http lin eai article log jre details otn 最小生成樹 算法圖解: http://baike.baidu.com/link?url=hGNkWIOLRJ_LDWMJRECxCPKUw7pI3s8AH5kj-944RwgeBSa9hGpT