對於這種邊權難以直接維護的都直接考慮brouvka演算法。
顯然,我們要做的是實現乙個可以查詢&x最大的資料結構。
可以先對於所有權值建立一顆01-trie樹。
考慮在trie樹查詢答案的過程,可以考慮乙個從高位到低位的貪心。
當x的第i位為1時,最優策略一定是能走1就走1。
當x的第i位為0時,既可以走0也可以走1。
因此可以用乙個類似線段樹合併的方式,把每乙個trie樹上的節點右兒子合併到左兒子上。
然後直接按照brouvka演算法的套路搞一下就行了。
#include#include#include#include#include#include#include#include#include#include#define n 220000
#define l 200000
#define m 8000000
#define eps 1e-7
#define inf 1e9+70
#define db double
#define ll long long
#define ldb long double
using namespace std;
inline int read()
while(isdigit(ch))
return x*flag;
}int v[n],f[n];
int find(int x)
void merge(int x,int y)
struct nodew[n],p[n];
bool operator<(node a,node b)
void pushup(int o)
void insert(int &o,int t,int x,int id)
if(!((1<<(t-1))&x))insert(lson,t-1,x,id);
else insert(rson,t-1,x,id);
pushup(o);
} int merge(int x,int y)
void solve(int o,int t)
node query(int o,int t,int x,int id)
; if((1<<(t-1))&x)
}else
return query(lson,t-1,x,id);
}}t;
int main()
for(int i=1;i<=n;i++)f[i]=v[f[i]];
if(cnt==1)break;
for(int i=0;i<=t.size;i++)t.lc[i]=t.rc[i]=0,t.maxv[i]=t.mixv[i]=-inf;
t.size=t.root=0;
for(int i=1;i<=n;i++)t.insert(t.root,m,a[i],find(i));
t.solve(t.root,m);
for(int i=1;i<=n;i++)w[i]=(node);
for(int x=1;x<=n;x++)
int tot=0;
for(int i=1;i<=n;i++)
if(w[i].x!=-1)
; }
} for(int i=1;i<=tot;i++)merge(p[i].x,p[i].y);
} printf("%lld",ans);
return 0;
}
uoj 176 新年的繁榮
給出乙個完全圖,邊權為兩點權值的and,求最大生成樹。這題用最小生成樹的boruvka演算法。大概就是每次找到每乙個聯通塊權值最大的邊,將這些聯通塊合併,直到只剩乙個聯通塊。因為每次聯通塊的個數至少減半,所以只會做log次操作。那麼這題相當於每個點有不同顏色,要找到每個點的異色點中最大的and值。扔...
UOJ176 新年的繁榮
題目鏈結 boruvka 演算法就是先把每個點看作乙個聯通塊,然後不斷在聯通塊之間找最優的邊進行合併。因為每次聯通塊的數量最少縮小一半。所以合併次數是 log 的 先把所有的點權掛到 trie 樹上。然後對於每個聯通塊進行合併的時候。對於聯通塊中的每個點都去 trie 上搜尋他能找到的最優秀的邊。也...
uoj 175 新年的網警
在這新年的第一天,猴族首領猴腮雷打算來整治一下網路風氣。這時,他聽說在乙個叫做 universal oj 使用者群 的 qq 群中有人在散播 開 謠言 車 於是他就派了一群網警把這個使用者群裡的人都抓了回來,試圖找到謠言的源頭。這個使用者群中有 nn 個人,這些人中存在 mm 對雙向的直接認識關係,...