bzoj 1579 [Usaco2009 Feb]Revampi…

来源:互联网 发布:移动进销存软件 编辑:程序博客网 时间:2024/05/21 00:54
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上的代码吧、、

ACCODE


{$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 to100 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 to100 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 shr1]:=tt;
end;
//=========================================================================
procedure update(x:longint); inline;
begin
  while x>1 do
    ifdist[heap[x]]<dist[heap[x shr 1]] then
    begin
     swap(x);
     x:=x shr 1;
    end elsebreak;
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;
    endelse
    if(h<=tot) and(dist[heap[i]]>dist[heap[h]]) then
    begin
     swap(h);
     i:=h;
    end elsebreak;
  end;
end;
//=========================================================================
procedure dij_heap; inline;
var i,j,u,v,ans:longint;
begin
  for i:=0 to capa do
    for j:=1 ton 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];
    whilei<>0 do
    beginv:=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;
    ifdist[t]<maxn thenbreak;   //就是加了这句优化就过了、、
  end; ans:=maxn;
  for i:=0 to capa do
    ifdist[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.
0 0
原创粉丝点击