poj3635

【题意】

给定n(n<=1000)个编号为0..n-1加油站的每单位油价格,再给定m(m<=10000)条边,并给出通过其所需油(<=100),询问q(q<=100)次,询问油箱容量为c(c<=100)时,s到e的所需最小费用

【输入】

第一行两个数字n、m

接下来一行n个数字表示每个加油站的单位油价

接下来m行每行三个数字u、v、d描述一条边

接下来一行一个数q表示询问数

之后q行每行描述一个询问c、s、e

【输出】

对于每个询问,输出一个数字表示最小费用,若不存在则输出'impossible'


heap+dijkstra

用dis[i][j]表示到达i节点油箱内还有j单位的油的最小费用

对于每次增光,分为两种,向别的节点前进或使油箱增加1单位的油

注意对堆的清空


program poj3635;
var
  ok:boolean;
  tot,now,who,q,n,m,i,j,k,u,v,d,c,s,e:longint;
  yes:array [0..1001] of boolean;
  root,p:array [0..1001] of longint;
  next,cost,point:array [0..20001] of longint;
  status,heap:array [0..200001] of longint;
  rank,dis:array [0..1001,0..101] of longint;

procedure swap (var a,b:longint);
var
  i:longint;
begin
  i:=a;
  a:=b;
  b:=i;
end;

procedure connect (u,v,d:longint);
begin
  inc(tot);
  point[tot]:=v;
  cost[tot]:=d;
  next[tot]:=root[u];
  root[u]:=tot;
end;

procedure delete (who,now:longint);
var
  i:longint;
begin
  if rank[who,now]=0 then exit;
  if rank[who,now]=tot then
    begin
      heap[tot]:=0;
      status[tot]:=0;
      rank[who,now]:=0;
      dec(tot);
      exit;
    end;
  i:=rank[who,now];
  swap(rank[who,now],rank[heap[tot],status[tot]]);
  swap(heap[i],heap[tot]);
  swap(status[i],status[tot]);
  heap[tot]:=0;
  status[tot]:=0;
  rank[who,now]:=0;
  dec(tot);
  if (i>1)and(dis[heap[i div 2],status[i div 2]]>dis[heap[i],status[i]]) then
    while (i>1)and(dis[heap[i div 2],status[i div 2]]>dis[heap[i],status[i]]) do
      begin
        swap(rank[heap[i div 2],status[i div 2]],rank[heap[i],status[i]]);
        swap(heap[i],heap[i div 2]);
        swap(status[i],status[i div 2]);
        i:=i div 2;
      end
                                                                         else
    while (dis[heap[i*2],status[i*2]]<dis[heap[i],status[i]])
    or(dis[heap[i*2+1],status[i*2+1]]<dis[heap[i],status[i]]) do
      if dis[heap[i*2],status[i*2]]<dis[heap[i*2+1],status[i*2+1]] then
        begin
          swap(rank[heap[i],status[i]],rank[heap[i*2],status[i*2]]);
          swap(heap[i*2],heap[i]);
          swap(status[i*2],status[i]);
          i:=i*2;
        end
                                                                   else
        begin
          swap(rank[heap[i],status[i]],rank[heap[i*2+1],status[i*2+1]]);
          swap(heap[i*2+1],heap[i]);
          swap(status[i*2+1],status[i]);
          i:=i*2+1;
        end;
end;

procedure insert (who,now:longint);
var
  i:longint;
begin
  inc(tot);
  heap[tot]:=who;
  status[tot]:=now;
  rank[who,now]:=tot;
  i:=tot;
  while (i>1)and(dis[heap[i div 2],status[i div 2]]>dis[heap[i],status[i]]) do
    begin
      swap(rank[heap[i div 2],status[i div 2]],rank[who,now]);
      swap(heap[i],heap[i div 2]);
      swap(status[i],status[i div 2]);
      i:=i div 2;
    end;
end;

procedure heap_dijkstra;
begin
  while tot>0 do
    begin
      now:=status[1];
      who:=heap[1];
      if who=e then
        begin
          ok:=true;
          writeln(dis[who,now]);
          exit;
        end;
      delete(who,now);
      if (now<c)and(dis[who,now+1]>dis[who,now]+p[who]) then
        begin
          delete(who,now+1);
          dis[who,now+1]:=dis[who,now]+p[who];
          insert(who,now+1);
        end;
      k:=root[who];
      while k<>0 do
        begin
          if (now>=cost[k])and(dis[who,now]<dis[point[k],now-cost[k]]) then
            begin
              delete(point[k],now-cost[k]);
              dis[point[k],now-cost[k]]:=dis[who,now];
              insert(point[k],now-cost[k]);
            end;
          k:=next[k];
        end;
    end;
end;

function dfs (now:longint):boolean;
var
  i:longint;
begin
  if now=e then exit(true);
  yes[now]:=true;
  i:=root[now];
  while i<>0 do
    begin
      if (not yes[point[i]])and(cost[i]<=c)and(dfs(point[i])) then exit(true);
      i:=next[i];
    end;
  exit(false);
end;

begin
  read(n,m);
  for i:=1 to n do
    read(p[i]);
  tot:=0;
  for i:=1 to m do
    begin
      read(u,v,d);
      inc(u);
      inc(v);
      connect(u,v,d);
      connect(v,u,d);
    end;
  read(q);
  while q<>0 do
    begin
      dec(q);
      fillchar(yes,sizeof(yes),false);
      read(c,s,e);
      inc(s);
      inc(e);
      if not dfs(s) then
        begin
          writeln('impossible');
          continue;
        end;
      fillchar(heap,sizeof(heap),0);
      fillchar(dis,sizeof(dis),63);
      fillchar(rank,sizeof(rank),0);
      tot:=0;
      dis[s,0]:=0;
      insert(s,0);
      ok:=false;
      heap_dijkstra;
    end;
end.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值