noip2013货车运输 最大生成树+LCA 【pascal】

裸的最大生成树+LCA=。=,两个模板一下就好=w=

type
    rec=record
        ll,rr,len:longint;
end;

var
    n,m,l               :longint;
    i,j                 :longint;
    a                   :array[0..50010] of rec;
    f,d,last            :array[0..10010] of longint;
    flag                :array[0..10010] of boolean;
    pre,other,len       :array[0..100010] of longint;
    dis,jump            :array[0..10010,0..20] of longint;
function min(a,b:longint):longint;
begin
   if a<b then exit(a) else exit(b);
end;
//
procedure swap(var a,b:longint);
var
    c:longint;
begin
   c:=a;a:=b;b:=c;
end;
//
procedure connect(x,y,z:longint);
begin
   inc(l);
   pre[l]:=last[x];
   last[x]:=l;
   other[l]:=y;
   len[l]:=z;
end;

procedure dfs(x:longint);
var
    p,q:longint;
begin
   q:=last[x];
   while (q<>0) do
   begin
      p:=other[q];
      if not flag[p] then
      begin
         flag[p]:=true;
         d[p]:=d[x]+1;
         jump[p,0]:=x;
         dis[p,0]:=len[q];
         dfs(p);
      end;
      q:=pre[q];
   end;
end;

procedure sort(l,r: longint);
var
         i,j,x: longint;
         y:rec;
begin
         i:=l;
         j:=r;
         x:=a[(l+r) div 2].len;
         repeat
           while a[i].len<x do inc(i);
           while x<a[j].len do dec(j);
           if not(i>j) then
             begin
                y:=a[i];
                a[i]:=a[j];
                a[j]:=y;
                inc(i);
                j:=j-1;
             end;
         until i>j;
         if l<j then sort(l,j);
         if i<r then sort(i,r);
end;
//
function get_father(x:longint):longint;
begin
    if x=f[x] then exit(x);
    f[x]:=get_father(f[x]);
    exit(f[x]);
end;

procedure max_tree;
var
    t,aa,b:longint;
    i:longint;
begin
   t:=0;
   for i:=m downto 1 do
   begin
      if (t=m-1) then break;
      aa:=get_father(a[i].ll);
      b:=get_father(a[i].rr);
      if (aa<>b) then
      begin
         f[b]:=aa;
         inc(t);
         connect(a[i].ll,a[i].rr,a[i].len);
         connect(a[i].rr,a[i].ll,a[i].len);
      end;
   end;
end;
//
procedure lca;
var
    ans,x,y:longint;
    i,j :longint;
begin
   read(x,y);
   if (get_father(x)<>get_father(y)) then
   begin
      writeln(-1);
      exit;
   end;
   //
   ans:=maxlongint;
   if (d[x]>d[y]) then swap(x,y);
   for j:=0 to 15 do
    if ((1<<j) and (d[y]-d[x]))<>0 then
    begin
       ans:=min(ans,dis[y,j]);
       y:=jump[y,j];
    end;
    //
    if (x<>y) then
    begin
       for j:=15 downto 0 do
        if (jump[x,j]<>jump[y,j]) then
        begin
           ans:=min(ans,dis[x,j]);
           ans:=min(ans,dis[y,j]);
           x:=jump[x,j];
           y:=jump[y,j];
        end;
        //
        ans:=min(ans,dis[y,0]);
        ans:=min(ans,dis[x,0]);
    end;
    writeln(ans);
end;

begin
   read(n,m);
   for i:=1 to n do f[i]:=i;
   for i:=1 to m do read(a[i].ll,a[i].rr,a[i].len);
   sort(1,m);
   max_tree;
   d[1]:=1;
   flag[1]:=true;
   dfs(1);
   for j:=1 to 15 do
    for i:=1 to n do
    begin
       jump[i,j]:=jump[jump[i,j-1],j-1];
       dis[i,j]:=min(dis[i,j-1],dis[jump[i,j-1],j-1]);
    end;
   //
   read(m);
   for i:=1 to m do lca;
end.
——by Eirlys


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值