题意:给一个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.