NOIP2013 D1 T3 货车运输 树上倍增lca+Kruskal
2016-05-18 20:24
567 查看
分析:先跑一边最大生成树,然后进行树上倍增求lca。
g[i,j]表示节点i的第2^j个祖先。w[i,j]表示节点i到第2^j个祖先的路上的最小值。
代码:
g[i,j]表示节点i的第2^j个祖先。w[i,j]表示节点i到第2^j个祖先的路上的最小值。
代码:
const maxn=10000; maxm=50000; var n,e,maxd,m:longint; a:array[0..maxm,1..3] of longint; g,w:array[1..maxn,0..16] of longint; last,f,d,fa,value:array[1..maxn] of longint; side:array[1..maxn*2] of record x,y,z,next:longint; end; procedure init; var i,x,y,z:longint; begin readln(n,m); for i:=1 to m do begin readln(x,y,z); a[i,1]:=x; a[i,2]:=y; a[i,3]:=z; end; end; procedure qsort(l,r:longint); var i,j,k:longint; begin if l>=r then exit; i:=l; j:=r; k:=a[(i+j) div 2,3]; repeat while a[i,3]>k do inc(i); while a[j,3]<k do dec(j); if i<=j then begin a[0]:=a[i];a[i]:=a[j];a[j]:=a[0]; inc(i);dec(j); end; until i>j; qsort(i,r); qsort(l,j); end; function find(x:longint):longint; begin if f[x]=x then exit(x); find:=find(f[x]); f[x]:=find; end; procedure add(x,y,z:longint); begin inc(e); side[e].x:=x; side[e].y:=y; side[e].z:=z; side[e].next:=last[x]; last[x]:=e; inc(e); side[e].x:=y; side[e].y:=x; side[e].z:=z; side[e].next:=last[y]; last[y]:=e; end; procedure kruskal; var i:longint; begin for i:=1 to n do f[i]:=i; for i:=1 to m do if find(a[i,1])<>find(a[i,2]) then begin add(a[i,1],a[i,2],a[i,3]); f[find(a[i,1])]:=find(a[i,2]); end; end; procedure dfs(x,dep:longint); var i:longint; begin if dep>maxd then maxd:=dep; d[x]:=dep; i:=last[x]; while i>0 do with side[i] do begin if y<>fa[x] then begin fa[y]:=x; value[y]:=z; dfs(y,dep+1); end; i:=next; end; end; function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end; procedure bz; var i,j:longint; begin for i:=1 to n do if fa[i]>0 then begin g[i,0]:=fa[i]; w[i,0]:=value[i]; end else begin g[i,0]:=-1; w[i,0]:=maxlongint div 3; end; maxd:=trunc(ln(maxd)/ln(2)); for j:=1 to maxd do for i:=1 to n do if g[i,j-1]>-1 then begin g[i,j]:=g[g[i,j-1],j-1]; w[i,j]:=min(w[i,j-1],w[g[i,j-1],j-1]); end else begin g[i,j]:=-1; w[i,j]:=maxlongint div 3; end; end; function lca(x,y:longint):longint; var i:longint; begin if find(x)<>find(y) then exit(-1); if d[x]<d[y] then begin x:=x xor y; y:=x xor y; x:=x xor y; end; lca:=maxlongint div 3; for i:=maxd downto 0 do if (g[x,i]>-1)and(d[g[x,i]]>=d[y]) then begin lca:=min(w[x,i],lca); x:=g[x,i]; end; for i:=maxd downto 0 do if g[x,i]<>g[y,i] then begin lca:=min(lca,w[x,i]); lca:=min(lca,w[y,i]); x:=g[x,i]; y:=g[y,i]; end; if x=y then exit; lca:=min(lca,value[x]); lca:=min(lca,value[y]); end; procedure main; var i,q,x,y:longint; begin qsort(1,m); kruskal; for i:=1 to n do if fa[i]=0 then dfs(i,1); bz; readln(q); for i:=1 to q do begin readln(x,y); writeln(lca(x,y)); end; end; begin init; main; end.
相关文章推荐
- 模板-根据中序,后序建树层次遍历输出
- 324. Wiggle Sort II【M】【33】
- 学习进度表
- 《浪潮之巅》阅读笔记
- Win32程序资源的使用
- 慕课网二次学习(二)
- C++ const限定符详细说明
- 42
- 加载本地文件到Hive表出现NULL列的解决办法
- 关于math头文件
- ECSHOP account_log,pay_log,user_account 三个表的用途与区别 用户余额的数据库表和函数
- iOS9的3D Touch
- 斜率优化 Snowdrop修长廊 scu dp练习B题
- serializable接口作用以及实例展示
- 堆排序
- 背包问题之5
- Fragment上
- 主工程与依赖的module工程R文件消失
- hibernate
- hdu1757 A Simple Math Problem(矩阵快速幂)