【NOIP2016练习&BZOJ2125】T3 sp (树上倍增,最短路)

题意:给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径。

对于80%的数据环的个数<=1

对于100%的数据N<=10000,Q<=10000

思路:bzoj原题

        只会80,正解听说是仙人掌

        对于80每个询问的最优解必定是一棵树或一棵树+一条边,因为环的个数<=1

        倍增LCA求距离,枚举树上加哪条边即可

        

  1 var f,g:array[1..100000,0..20]of longint;
  2     head,vet,next,fa,dep,a,b,c,len:array[1..200000]of longint;
  3     n,i,tx,ty,tz,ans,w,tot,m,q,x,y,j:longint;
  4 
  5 function min(x,y:longint):longint;
  6 begin
  7  if x<y then exit(x);
  8  exit(y);
  9 end;
 10 
 11 procedure add(a,b,c:longint);
 12 begin
 13  inc(tot);
 14  next[tot]:=head[a];
 15  vet[tot]:=b;
 16  len[tot]:=c;
 17  head[a]:=tot;
 18 end;
 19 
 20 procedure swap(var x,y:longint);
 21 var t:longint;
 22 begin
 23  t:=x; x:=y; y:=t;
 24 end;
 25 
 26 function lca(x,y:longint):longint;
 27 var i,d:longint;
 28 begin
 29  if dep[x]<dep[y] then swap(x,y);
 30  d:=dep[x]-dep[y];
 31  for i:=0 to 14 do
 32   if d and (1<<i)>0 then x:=f[x,i];
 33  for i:=14 downto 0 do
 34   if f[x,i]<>f[y,i] then
 35   begin
 36    x:=f[x,i]; y:=f[y,i];
 37   end;
 38  if x=y then exit(x);
 39  exit(f[x,0]);
 40 end;
 41 
 42 function clac(x,y:longint):longint;
 43 var i,d:longint;
 44 begin
 45  if dep[x]<dep[y] then swap(x,y);
 46  d:=dep[x]-dep[y];
 47  clac:=0;
 48  for i:=0 to 14 do
 49   if d and (1<<i)>0 then
 50   begin
 51    clac:=clac+g[x,i];
 52    x:=f[x,i];
 53   end;
 54 end;
 55 
 56 function ask(x,y:longint):longint;
 57 var t:longint;
 58 begin
 59  t:=lca(x,y);
 60  exit(clac(x,t)+clac(y,t));
 61 end;
 62 
 63 function find(k:longint):longint;
 64 begin
 65  if fa[k]<>k then fa[k]:=find(fa[k]);
 66  exit(fa[k]);
 67 end;
 68 
 69 procedure dfs(u,pre:longint);
 70 var i,e,v:longint;
 71 begin
 72  for i:=1 to 14 do
 73  begin
 74   if dep[u]<1<<i then break;
 75   f[u,i]:=f[f[u,i-1],i-1];
 76   g[u,i]:=g[u,i-1]+g[f[u,i-1],i-1];
 77  end;
 78  e:=head[u];
 79  while e<>0 do
 80  begin
 81   v:=vet[e];
 82   if v<>pre then
 83   begin
 84    dep[v]:=dep[u]+1;
 85    f[v,0]:=u; g[v,0]:=len[e];
 86    dfs(v,u);
 87   end;
 88   e:=next[e];
 89  end;
 90 end;
 91 
 92 begin
 93  assign(input,'sp.in'); reset(input);
 94  assign(output,'sp.out'); rewrite(output);
 95  readln(n,m,q);
 96  for i:=1 to n do fa[i]:=i;
 97  for i:=1 to m do
 98  begin
 99   readln(tx,ty,tz);
100   x:=find(tx); y:=find(ty);
101   if x<>y then
102   begin
103    fa[y]:=x;
104    add(tx,ty,tz);
105    add(ty,tx,tz);
106   end
107    else begin inc(w); a[w]:=tx; b[w]:=ty; c[w]:=tz; end;
108  end;
109  dfs(1,-1);
110  for i:=1 to q do
111  begin
112   read(tx,ty);
113   ans:=ask(tx,ty);
114   for j:=1 to w do
115   begin
116    ans:=min(ans,ask(tx,a[j])+c[j]+ask(ty,b[j]));
117    ans:=min(ans,ask(ty,a[j])+c[j]+ask(tx,b[j]));
118   end;
119   writeln(ans);
120  end;
121  close(input);
122  close(output);
123 end.

 

posted on 2016-11-03 16:24  myx12345  阅读(363)  评论(0编辑  收藏  举报

导航