有个简单的想法就是将道路设成点,然后对于每一个询问用SPFA求解,能过前50%的点。
这道题有个特殊的地方,就是m≤300,这是个Floyd的数据规模,而且询问数比较小,可以考虑把每两条路之间的距离用Floyd预处理出来,然后对于每个询问,枚举两个点分别连向哪两条路,复杂度O(m^2*l+m^3+Tm^2),能过100%的点。
type
edge=record
y,v,next:longint;
end;
const
mx=200000;
INF=maxlongint>>1;
var
map:array[0..2000000] of edge;
dis:array[0..301,0..301] of longint;
first:array[0..mx] of longint;
n,m,i,j,k,x,v,a,b,s,cnt,t,tt:longint;
ans:int64;
procedure ins(x,y,v:longint);
begin
inc(s);map[s].y:=y;map[s].v:=v;
map[s].next:=first[x];first[x]:=s;
end;
function min(a,b:longint):longint;
begin if (a<b) then exit(a) else exit(b); end;
begin
assign(input,'map.in');reset(input);
assign(output,'map.out');rewrite(output);
read(n,m);
for i:=1 to m do
begin
read(k);
for j:=1 to k do
begin
read(x,v);
ins(n+i,x,v);
ins(x,n+i,v);
end;
end;
for i:=1 to m do
for j:=1 to m do
dis[i][j]:=INF;
for i:=1 to m do
dis[i][i]:=0;
for i:=1 to m do
begin
t:=first[n+i];
while t>0 do
begin
tt:=first[map[t].y];
while tt>0 do
begin
dis[i][map[tt].y-n]:=min(dis[i][map[tt].y-n],map[t].v+map[tt].v);
tt:=map[tt].next;
end;
t:=map[t].next;
end;
end;
for k:=1 to m do
for i:=1 to m do
for j:=1 to m do
dis[i][j]:=min(dis[i][j],dis[i][k]+dis[k][j]);
read(a,b);
while (a<>0) do
begin
ans:=INF;
t:=first[a];
while t>0 do
begin
tt:=first[b];
while tt>0 do
begin
ans:=min(ans,map[t].v+map[tt].v+dis[map[t].y-n][map[tt].y-n]);
tt:=map[tt].next;
end;
t:=map[t].next;
end;
if ans=INF
then writeln(-1)
else writeln(ans);
read(a,b);
end;
close(input);close(output);
end.