http://www.lydsy.com/JudgeOnline/problem.php?id=1579
http://poj.org/problem?id=3635
两题实在长,我就不贴了。
这两题的做法都是一样的,在dij的时候多加一维分别表示当前剩余的更新次数(poj里面是余油量)。
很多人都是开个二维数组搞的,但是今天看到一个拆点的做法相当神奇~~原文地址如下:
http://hi.baidu.com/lrc2222/blog/item/e40177f76c37b338720eecc7 .html
大意就是把n个点分成k层,k即原方法中的第二位,然后把0长度的边连在不同的层之间表示更新路径使时间为0,相同层里面的点连原时间长度的边表示不更新路径直接走。最后在每一层里面的终点值里取个最优的输出。
对于poj里面的那题所连的边都是在不同层之间的。向较上一层的自己连一条长度为一单位油价的边表示加油,向下d层的j点连一条权值为0的边表示有一条长度为d的路与j连接。
这样建完图就是裸裸的dij+heap了~~~
不过poj上的那题一早上总是超时。。。怎么卡时都不过。。。后来看标程发现一个露加的优化:
当第0层的终点有值的时候就退出。
因为用的是dij,正确性显而易见。。。
但是bzoj上的那道题就不能用这个优化了。。。有可能k次更新不许要都用完就已经走到了。。。
这里就贴一个poj上的代码吧、、
AC CODE
{$inline on}
program pku_3635;
const maxn=99999999;
var line,next,g:array[1..2100000] of longint;
en,dist,pi,heap:array[1..101000] of longint;
c:array[1..1000] of longint;
lim,s,t,n,len,tot,capa:longint;
//=========================================================================
procedure ins(x,y,z:longint); inline;
begin
inc(len); line[len]:=y; g[len]:=z;
next[len]:=en[x]; en[x]:=len;
end;
//=========================================================================
procedure init; inline;
var i,j,m,x,y,z:longint;
begin
readln(n,m);
for i:=1 to n do read(c[i]);
for i:=1 to m do
begin
readln(x,y,z);
inc(x); inc(y);
for j:=z to 100 do
begin
ins(j*n+x,(j-z)*n+y,0);
ins(j*n+y,(j-z)*n+x,0);
end;
end;
for i:=1 to n do
for j:=1 to 100 do
ins((j-1)*n+i,j*n+i,c[i]);
end;
//=========================================================================
procedure swap(x:longint); inline;
var tt:longint;
begin
tt:=pi[heap[x]]; pi[heap[x]]:=pi[heap[x shr 1]]; pi[heap[x shr 1]]:=tt;
tt:=heap[x]; heap[x]:=heap[x shr 1]; heap[x shr 1]:=tt;
end;
//=========================================================================
procedure update(x:longint); inline;
begin
while x>1 do
if dist[heap[x]]<dist[heap[x shr 1]] then
begin
swap(x);
x:=x shr 1;
end else break;
end;
//=========================================================================
procedure insert(x:longint); inline;
begin
inc(tot); heap[tot]:=x; pi[x]:=tot;
update(tot);
end;
//=========================================================================
procedure del; inline;
var i,g,h:longint;
begin
pi[heap[tot]]:=0; heap[1]:=heap[tot]; dec(tot); i:=1;
while i<tot do
begin
g:=i shl 1; h:=i shl 1+1;
if (g<=tot) and (dist[heap[i]]>dist[heap[g]]) then
begin
if (h<=tot) and (dist[heap[g]]>dist[heap[h]]) then
begin
swap(h);
i:=h;
end else
begin
swap(g);
i:=g;
end;
end else
if (h<=tot) and (dist[heap[i]]>dist[heap[h]]) then
begin
swap(h);
i:=h;
end else break;
end;
end;
//=========================================================================
procedure dij_heap; inline;
var i,j,u,v,ans:longint;
begin
for i:=0 to capa do
for j:=1 to n do
begin
dist[i*n+j]:=maxn;
pi[i*n+j]:=0;
end;
heap[1]:=s; tot:=1; pi[s]:=1; dist[s]:=0;
while tot>0 do
begin
u:=heap[1]; pi[u]:=0; del; i:=en[u];
while i<>0 do
begin v:=line[i];
if v<=lim then
if dist[u]+g[i]<dist[v] then
begin
dist[v]:=dist[u]+g[i];
if pi[v]=0 then insert(v) else
update(pi[v]);
end;
i:=next[i];
end;
if dist[t]<maxn then break;
//就是加了这句优化就过了、、
end; ans:=maxn;
for i:=0 to capa do
if dist[i*n+t]<ans then
ans:=dist[i*n+t];
if ans=maxn then
writeln('impossible') else
writeln(ans);
end;
//=========================================================================
procedure main; inline;
var query:longint;
begin
readln(query);
for query:=1 to query do
begin
readln(capa,s,t);
inc(s); inc(t);
lim:=capa*n+n;
//因为有油箱容量的限制,有些点是非法的、、
dij_heap;
end;
end;
//=========================================================================
begin
while not(eof) do
begin
init;
main;
end;
end.
http://poj.org/problem?id=3635
两题实在长,我就不贴了。
这两题的做法都是一样的,在dij的时候多加一维分别表示当前剩余的更新次数(poj里面是余油量)。
很多人都是开个二维数组搞的,但是今天看到一个拆点的做法相当神奇~~原文地址如下:
http://hi.baidu.com/lrc2222/blog/item/e40177f76c37b338720eecc7
大意就是把n个点分成k层,k即原方法中的第二位,然后把0长度的边连在不同的层之间表示更新路径使时间为0,相同层里面的点连原时间长度的边表示不更新路径直接走。最后在每一层里面的终点值里取个最优的输出。
对于poj里面的那题所连的边都是在不同层之间的。向较上一层的自己连一条长度为一单位油价的边表示加油,向下d层的j点连一条权值为0的边表示有一条长度为d的路与j连接。
这样建完图就是裸裸的dij+heap了~~~
不过poj上的那题一早上总是超时。。。怎么卡时都不过。。。后来看标程发现一个露加的优化:
当第0层的终点有值的时候就退出。
因为用的是dij,正确性显而易见。。。
但是bzoj上的那道题就不能用这个优化了。。。有可能k次更新不许要都用完就已经走到了。。。
这里就贴一个poj上的代码吧、、
AC CODE
{$inline on}
program pku_3635;
const maxn=99999999;
var line,next,g:array[1..2100000] of longint;
//=========================================================================
procedure ins(x,y,z:longint); inline;
begin
end;
//=========================================================================
procedure init; inline;
var i,j,m,x,y,z:longint;
begin
end;
//=========================================================================
procedure swap(x:longint); inline;
var tt:longint;
begin
end;
//=========================================================================
procedure update(x:longint); inline;
begin
end;
//=========================================================================
procedure insert(x:longint); inline;
begin
end;
//=========================================================================
procedure del; inline;
var i,g,h:longint;
begin
end;
//=========================================================================
procedure dij_heap; inline;
var i,j,u,v,ans:longint;
begin
end;
//=========================================================================
procedure main; inline;
var query:longint;
begin
end;
//=========================================================================
begin
end.