【题意】
给定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.