题目大意:
在一个地图上,每条路径有长度,以及它的限制高度。 一辆卡车要从A地到B地, 卡车的最大能装h高度的货物。 求这辆卡车从A到B所能装下的最高货物的时候, 最短路径是多少。
分析与总结:
和 HDU 1839 相类似。 卡车载的货物高度h从小到大依次枚举时,满足条件的A到B的路径数量是依次递减的,直到没有路径为止。因此满足单调性,可以用二分法对卡车的载货量进行二分,在求最短路。 如果能够求出最短路,那么left=mid+1, 否则right=mid.
注意,能够求出最短路的同时,还要保存下答案。
代码:
[cpp]
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int INF = 0x7fffffff;
const int VN = 1005;
const int EN = VN*VN/2;
struct Edge{
int v,next;
int h, len;
}E[EN];
int n;
int m;
int size;
int head[VN];
int d[VN];
int limit;
bool inq[VN];
void init(){
size=0;
memset(head, -1, sizeof(head));
}
void addEdge(int u,int v,int h,int l){
E[size].v=v;
if(h!=-1)E[size].h=h;
else E[size].h=INF;
E[size].len=l;
E[size].next=head[u];
head[u]=size++;
}
int SPFA(int src, int end){
for(int i=1; i<=n; ++i)d[i]=INF;
memset(inq, 0, sizeof(inq));
queue<int>q;
d[src] = 0;
q.push(src);
while(!q.empty()){
int u=q.front(); q.pop();
inq[u]=false;
for(int e=head[u]; e!=-1; e=E[e].next)if(E[e].h>=limit){
int tmp = d[u]+E[e].len;
if(d[E[e].v] > tmp){
d[E[e].v] = tmp;
if(!inq[E[e].v]){
inq[E[e].v]=true;
q.push(E[e].v);
}
}
}
}
return d[end];
}
int main(){
int cas=1,u,v,h,l,start,end,hh;
while(~scanf("%d%d",&n,&m) && n+m){
if(cas!=1)puts("");
init();
for(int i=0; i<m; ++i){
scanf("%d%d%d%d",&u,&v,&h,&l);
addEdge(u,v,h,l);
addEdge(v,u,h,l);
}
scanf("%d%d%d",&start,&end,&hh);
int ans,ans_h=0,ans_len=INF,left=0, right=hh+1;
while(left<right){
limit = (left+right)》1;
ans=SPFA(start, end);
if(ans!=INF){
left=limit+1;
if(limit>ans_h){
ans_h=limit;
ans_len=ans;
}