原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2962
题意:一个货车要把一些货物从一个地方Start运到另一个地方End,希望每次运货尽可能多的运输货物。但是一些道路可能会限制运货的高度(-1时表示不限高度),而且出于安全问题,货车运的货不会超过一定高度H。求出不超过H的高度下,最多能运多少货物(用高度来衡量运输的货物量,即问不超过H下的最大高度)?并且求出在这个最大运货量的情况下,最短路径长度是多少?
思路:二分枚举最大高度,然后跑dijksra。注意格式…
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int N = 2e5+5;
const int Inf = 0x3f3f3f3f;
int vis[N],dis[N];
int Head[N];
int n,m,cnt,H;
int Start,End;
struct node{
int to,h,w;
int Next;
bool operator < (const node &a) const{
return a.w < w;
}
} Edge[N],Now,Next;
void init() {
memset(Head,-1,sizeof(Head));
cnt = 0;
}
void Add(int u,int v,int h,int w){
Edge[cnt].to = v;
Edge[cnt].h = h;
Edge[cnt].w = w;
Edge[cnt].Next = Head[u];
Head[u] = cnt ++;
}
bool dijkstra(int s,int h){
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[s] = 0;
// vis[s] = 1;
priority_queue<node> q;
Now.to = s;
q.push(Now);
while(!q.empty()){
Now = q.top();
q.pop();
s = Now.to;
if(vis[s]) continue;
vis[s] = 1;
for(int i=Head[s]; ~i; i = Edge[i].Next){
int v = Edge[i].to;
if(!vis[v] && Edge[i].h >= h && dis[v] > dis[s] + Edge[i].w){ //在这里还要判断这条路高度是否超过枚举的答案高度
dis[v] = dis[s] + Edge[i].w;
Next.to = v;
Next.w = dis[v];
q.push(Next);
}
}
}
if(dis[End] != Inf) return true; //枚举的这个答案高度能走到End
else return false;
}
int main(){
int Case = 1;
while(~scanf("%d%d",&n,&m),(n && m)){
if(Case != 1) puts("");
init();
int u,v,h,w,L,R;
for(int i=0;i<m;i++){
scanf("%d%d%d%d",&u,&v,&h,&w);
if(h == -1) h = Inf;
Add(u,v,h,w);
Add(v,u,h,w);
}
scanf("%d%d%d",&Start,&End,&H);
L = 1,R = H;
int ans1 = -1,ans2 = 0;
while(L <= R){
int mid = (R-L)/2 + L;
if(dijkstra(Start,mid)){
ans1 = mid;
ans2 = dis[End]; //这里要存一下当前枚举高度下的最短路长度
L = mid + 1;
}
else {
R = mid - 1;
}
}
printf("Case %d:\n",Case ++);
if(ans1 == -1) puts("cannot reach destination");
else {
printf("maximum height = %d\n", ans1);
printf("length of shortest route = %d\n", ans2);
}
}
return 0;
}