日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

克鲁斯卡尔重构树

發布時間:2024/4/11 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 克鲁斯卡尔重构树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

水的時候看到的算法

正文

對于一些問題,比如什么在一幅圖從一個點開始經過的邊小于等于某個值所能達到的點集中求balabala
首先搞出最小生成樹(顯然只有最小生成樹上的邊有用)
然后從小到大枚舉邊,把邊所連的兩個點合并成一個新的點(新的點的權值等于邊的權值),新的點繼承原來兩個點相連的邊
將所有點合并完后,我們開始建克魯斯卡爾重構樹,這棵樹的點就是原圖中的點加上新建的點,這棵樹的邊是每個新建的點向合并的兩個點的連邊
這樣就會有很好的性質,在一個節點子樹內的所有葉子所代表的點在原圖中互相達到經過的邊小于等于這個節點的權值
然后就可以用各種算法來操作一波了

例題

[bzoj3551][ONTAK2010]Peaks加強版
本題其實大概是裸題了吧
直接克魯斯卡爾重構樹+主席樹就好了
代碼

#include<cstdio> #include<cctype> #include<algorithm> namespace fast_IO {const int IN_LEN=1000000,OUT_LEN=1000000;char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf,*lastin=ibuf+IN_LEN,*lastout=obuf+OUT_LEN-1;inline char getchar_(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,IN_LEN,stdin),ih==lastin)?EOF:*ih++;}inline void putchar_(const char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}inline void flush(){fwrite(obuf,1,oh-obuf,stdout);} } using namespace fast_IO; #define getchar() getchar_() #define putchar(x) putchar_((x)) #define rg register typedef long long ll; template <typename T> inline T max(const T a,const T b){return a>b?a:b;} template <typename T> inline T min(const T a,const T b){return a<b?a:b;} template <typename T> inline void mind(T&a,const T b){a=a<b?a:b;} template <typename T> inline void maxd(T&a,const T b){a=a>b?a:b;} template <typename T> inline T abs(const T a){return a>0?a:-a;} template <typename T> inline void Swap(T&a,T&b){T c=a;a=b;b=c;} template <typename T> inline T gcd(const T a,const T b){if(!b)return a;return gcd(b,a%b);} template <typename T> inline T lcm(const T a,const T b){return a/gcd(a,b)*b;} template <typename T> inline T square(const T x){return x*x;}; template <typename T> inline void read(T&x) {char cu=getchar();x=0;bool fla=0;while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}while(isdigit(cu))x=x*10+cu-'0',cu=getchar();if(fla)x=-x; } template <typename T> inline void printe(const T x) {if(x>=10)printe(x/10);putchar(x%10+'0'); } template <typename T> inline void print(const T x) {if(x<0)putchar('-'),printe(-x);else printe(x); } const int maxn=200005,maxm=500005; int n,m,q,h[maxn],lsh[maxn],lshn; struct edge {int u,v,w;bool operator <(const edge&b)const{return w<b.w;} }Q[maxm]; int bcj[maxn],node; int fa[maxn][21],val[maxn]; void newnode() {node++;bcj[node]=node;fa[node][0]=node; } int find(const int x) {if(x==bcj[x])return x;return bcj[x]=find(bcj[x]); } int son[maxn][2]; int tid[maxn],tim,endd[maxn],bak[maxn]; int SZ[maxn]; void dfs(const int u) {tid[u]=++tim,bak[tim]=u;if(son[u][0])dfs(son[u][0]),dfs(son[u][1]);endd[u]=tim; } struct nd {nd *lson,*rson;int size; }*root[maxn],empty,*Null,P[maxn*20]; int usd; inline nd*newnd() {usd++;nd*r=&P[usd];r->lson=r->rson=Null,r->size=0;return r; } nd*insert(nd*dq,nd*las,const int l,const int r,const int v) {if(l!=r){const int mid=(l+r)>>1;if(v<=mid){dq->rson=las->rson;dq->lson=insert(newnd(),las->lson,l,mid,v);}else{dq->lson=las->lson;dq->rson=insert(newnd(),las->rson,mid+1,r,v);}}dq->size=las->size+1;return dq; } int kth(nd*dq,nd*las,const int l,const int r,const int k) {if(l==r)return l;const int v=dq->rson->size-las->rson->size,mid=(l+r)>>1;if(v<k)return kth(dq->lson,las->lson,l,mid,k-v);return kth(dq->rson,las->rson,mid+1,r,k); } int bz(int v,const int x) {for(rg int i=20;i>=0;i--)if(val[fa[v][i]]<=x)v=fa[v][i];return v; } int main() {empty.lson=empty.rson=Null=&empty;read(n),read(m),read(q);for(rg int i=1;i<=n;i++)read(h[i]),newnode(),lsh[i]=h[i],SZ[i]=1;std::sort(lsh+1,lsh+n+1);lshn=std::unique(lsh+1,lsh+n+1)-lsh-1;for(rg int i=1;i<=n;i++)h[i]=std::lower_bound(lsh+1,lsh+lshn+1,h[i])-lsh;for(rg int i=1;i<=m;i++)read(Q[i].u),read(Q[i].v),read(Q[i].w);std::sort(Q+1,Q+m+1);for(rg int i=1;i<=m;i++){const int u=Q[i].u,v=Q[i].v,U=find(u),V=find(v);if(U==V)continue;newnode();fa[U][0]=fa[V][0]=node;val[node]=Q[i].w;bcj[U]=bcj[V]=node;son[node][0]=U,son[node][1]=V;SZ[node]=SZ[U]+SZ[V];}for(rg int i=1;i<=20;i++)for(rg int j=1;j<=node;j++)fa[j][i]=fa[fa[j][i-1]][i-1];for(rg int i=1;i<=node;i++)if(fa[i][0]==i)dfs(i);root[0]=newnd();for(rg int i=1;i<=tim;i++)root[i]=insert(newnd(),root[i-1],0,lshn,h[bak[i]]);int lastans=0;while(q--){int v,x,k;read(v),read(x),read(k);v^=lastans,x^=lastans,k^=lastans;const int T=bz(v,x);if(SZ[T]<k){print(-1),putchar('\n');lastans=0;continue;}lastans=lsh[kth(root[endd[T]],root[tid[T]-1],0,lshn,k)];print(lastans),putchar('\n');}return flush(),0; }

總結

應用有局限性,但是思路還是很不錯的

總結

以上是生活随笔為你收集整理的克鲁斯卡尔重构树的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。