樹鏈剖分-入門題目
阿新 • • 發佈:2019-01-26
Query on a tree
題目大致意思就是: 給你一棵樹,有連個操作:
● 第一個是查詢任意兩個不同節點上的最短路徑上的最大權邊!
● 第二個操作修改某一條邊的權值;
對於一棵樹,數的深度如果很大,那麼每次查詢兩個葉子節點,時間複雜度還是很高的。所以我們就把樹分成一條一條的樹鏈,所謂樹鏈就是:沿著樹的一條路徑。 得到路徑後,我們可以用堆,線段樹進行維護。在一些題目中,樹鏈剖分題目,一般可以用dfs 進行剖鏈。
鄙人學習樹鏈剖分所用到資料:
,看這篇部落格主要知道什麼是樹鏈剖分,以及原理;知道樹鏈剖分部分,剖分樹鏈之後需要用一些資料結構維護,大部分用線段樹。線段樹比較常用。所以我也用線段樹;
有了以上知識儲備,做這個題目也比較輕鬆! 線段樹要會!!可以參考kuangbin題解來做;附上我AC程式碼,一是為了存個模板,二還請大佬指出錯誤!
#include<cstdio> #include<cstring> #include<cctype> #include<cmath> #include<set> #include<map> #include<list> #include<queue> #include<deque> #include<stack> #include<string> #include<vector> #include<iostream> #include<algorithm> #include<stdlib.h> #include<time.h> using namespace std; typedef long long LL; const int INF=2e9+1e8; const int MOD=1e9+7; const int MAXSIZE=2e4+100; const double eps=0.0000000001; void fre() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); } #define memst(a,b) memset(a,b,sizeof(a)) #define fr(i,a,n) for(int i=a;i<n;i++) int son[MAXSIZE],deep[MAXSIZE],father[MAXSIZE],num[MAXSIZE],top[MAXSIZE],p[MAXSIZE],fp[MAXSIZE],pos; int Treevalue[MAXSIZE]; // son 代表重兒子; deep 深度;father 父親節點;num 統計節點個數; //top 樹鏈的頭, p 某個節點線上段樹的位置 ; fp 線段樹某個位置在樹中的位置; //pos 是用來對樹的節點進行標號的; // 建圖部分 int first[MAXSIZE],ntot; struct Node { int to,next,val; }; struct NODE { int a,b,c; } input[MAXSIZE]; Node edge[MAXSIZE]; void init() { memst(first,-1); memst(son,-1); pos=ntot=0; } void addedge(int s,int t,int val) { edge[ntot].to=t,edge[ntot].val=val; edge[ntot].next=first[s],first[s]=ntot++; } // 剖分樹鏈 void dfs(int x,int pre,int _deep) { deep[x]=_deep; father[x]=pre; num[x]=1; for(int i=first[x]; i!=-1; i=edge[i].next) { int to=edge[i].to; if(to!=pre) { Treevalue[to]=edge[i].val; dfs(to,x,_deep+1); num[x]+=num[to]; if(son[x]==-1||num[to]>num[son[x]]) son[x]=to; } } return ; } void getlist(int x,int pr) { top[x]=pr; if(son[x]!=-1) // 如果存在重兒子,就沿著一直找下去 { p[x]=pos++; fp[p[x]]=x; getlist(son[x],pr); } else //直到到低端為止 { p[x]=pos++; fp[p[x]]=x; return ; } for(int i=first[x]; i!=-1; i=edge[i].next) { int to=edge[i].to; if(to!=son[x]&&to!=father[x]) getlist(to,to); //如果不是往回走 且 不是重兒子那麼就是新的樹鏈進行dfs金合歡花; } } //樹鏈剖分部分 完成 // 線段樹部分 struct TreeNode { int l,r,max; } tree[MAXSIZE*3]; void push_up(int i) { tree[i].max=max(tree[i<<1].max,tree[i<<1|1].max); } void build(int i,int l,int r) { tree[i].l=l,tree[i].r=r,tree[i].max=0; if(l==r) { tree[i].max=Treevalue[fp[l]]; return ; } int mid=(l+r)>>1; build(i<<1,l,mid); build(i<<1|1,mid+1,r); push_up(i); } int query(int i,int l,int r) { if(tree[i].l==l&&tree[i].r==r) return tree[i].max; int mid=(tree[i].l+tree[i].r)>>1; if(l>mid) return query(i<<1|1,l,r); else if(r<=mid) return query(i<<1,l,r); else return max(query(i<<1|1,mid+1,r),query(i<<1,l,mid)); } int getmax(int a,int b) { int res=0; int f1=top[a],f2=top[b]; while(f1!=f2) { if(deep[f1]>deep[f2]) { res=max(res,query(1,p[f1],p[a])); a=father[f1],f1=top[a]; } else { res=max(res,query(1,p[f2],p[b])); b=father[f2],f2=top[b]; } } if(a==b) return res; if(deep[a]>deep[b]) swap(a,b); return max(res,query(1,p[son[a]],p[b])); } void update(int i,int k,int val)//插點 { if(tree[i].l==k&&tree[i].r==k) { tree[i].max=val; return ; } int mid=(tree[i].l+tree[i].r)>>1; if(k>mid) update(i<<1|1,k,val); else update(i<<1,k,val); push_up(i); } void Debug(int i,int l,int r) { if(tree[i].r>r||tree[i].l<l) return ; printf("i=%d l=%d r=%d max=%d\n",i,tree[i].l,tree[i].r,tree[i].max); Debug(i<<1,l,r); Debug(i<<1|1,l,r); } int main() { int ncase,n; scanf("%d",&ncase); while(ncase--) { init(); scanf("%d",&n); for(int i=1; i<n; i++) { scanf("%d%d%d",&input[i].a,&input[i].b,&input[i].c); addedge(input[i].a,input[i].b,input[i].c); addedge(input[i].b,input[i].a,input[i].c); } dfs(1,0,0);//把圖變成一棵樹; getlist(1,1);//剖樹鏈; build(1,1,n-1); while(1) { char opt[10]; scanf("%s",opt); if(opt[0]=='D') break; if(opt[0]=='C') { int change_pos,value; scanf("%d%d",&change_pos,&value); int a=input[change_pos].a,b=input[change_pos].b; if(deep[a]>deep[b]) swap(a,b); update(1,p[b],value); } else { int a,b; scanf("%d%d",&a,&b); printf("%d\n",getmax(a,b)); } } } return 0; } /**************************************************/ /** Copyright Notice **/ /** writer: wurong **/ /** school: nyist **/ /** blog : http://blog.csdn.net/wr_technology **/ /**************************************************/