lca倍增演算法
阿新 • • 發佈:2019-02-16
HDU2586
要注意只有簡單邊相連的圖是一棵樹,樹有n-1條邊
倍增之前要先存雙向邊,以任意頂點為根(比如1)dfs遍歷確定樹。
倍增前求f[i,j]時先賦值為-1便於判斷f[ij-1]祖先存不存在
倍增時先將兩個點調至同一高度(注意最後的微調每次只上升一個高度)
program hdu2586; const maxm=15; var i,j,ans,t,l1,l,n,m,x,y,z:longint; f,g:array[0..40000,0..15]of longint; vis:array[0..40000]of boolean; edge:array[1..80000,1..3]of longint; deep:array[-1..40000]of longint; head:array[1..40000]of longint; procedure dfs(u,de:longint);//buildtree_root=1 var p:longint; begin vis[u]:=true; deep[u]:=de; p:=head[u]; while p<>-1 do begin if vis[edge[p,1]]=false then begin g[edge[p,1],0]:=edge[p,2]; f[edge[p,1],0]:=u; dfs(edge[p,1],de+1); end; p:=edge[p,3]; end; end; procedure make;//倍增 var j,i:longint; begin for j:=1 to maxm do for i:=1 to n do if f[i,j-1]<>-1 then begin f[i,j]:=f[f[i,j-1],j-1]; g[i,j]:=g[i,j-1]+g[f[i,j-1],j-1]; end; end; procedure find(x,y:longint); var tmp,i:longint; begin if deep[x]<deep[y] then begin tmp:=x;x:=y;y:=tmp; end; for i:=maxm downto 1 do if deep[f[x,i]]>deep[y] then begin ans:=ans+g[x,i]; x:=f[x,i]; end; while deep[x]>deep[y] do begin ans:=ans+g[x,0];x:=f[x,0]; end; if x=y then exit; for i:=maxm downto 1 do if f[x,i]<>f[y,i] then begin ans:=ans+g[x,i]+g[y,i]; x:=f[x,i]; y:=f[y,i]; end; while x<>y do begin ans:=ans+g[x,0]+g[y,0]; x:=f[x,0]; y:=f[y,0]; end; end; begin read(t); for l1:=1 to t do begin read(n,m); for i:=1 to n do head[i]:=-1; for i:=1 to n-1 do begin read(x,y,z); l:=l+1; edge[l,1]:=y; edge[l,2]:=z; edge[l,3]:=head[x]; head[x]:=l; l:=l+1; edge[l,1]:=x; edge[l,2]:=z; edge[l,3]:=head[y]; head[y]:=l; end; fillchar(f,sizeof(f),0);//father fillchar(g,sizeof(g),0);//distence fillchar(vis,sizeof(vis),false); for j:=0 to maxm do for i:=1 to n do f[i,j]:=-1;//f[1,0]:=-1;g[1,0]:=0; dfs(1,1); make; for i:=1 to m do begin ans:=0; read(x,y); find(x,y); writeln(ans); end; end; end.