hdu 2962 Trucking【二分+SPFA】

Trucking

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2329    Accepted Submission(s): 810

Problem Description

A certain local trucking company would like to transport some goods on a cargo truck from one place to another. It is desirable to transport as much goods as possible each trip. Unfortunately, one cannot always use the roads in the shortest route: some roads may have obstacles (e.g. bridge overpass, tunnels) which limit heights of the goods transported. Therefore, the company would like to transport as much as possible each trip, and then choose the shortest route that can be used to transport that amount.

For the given cargo truck, maximizing the height of the goods transported is equivalent to maximizing the amount of goods transported. For safety reasons, there is a certain height limit for the cargo truck which cannot be exceeded.

Input

The input consists of a number of cases. Each case starts with two integers, separated by a space, on a line. These two integers are the number of cities (C) and the number of roads (R). There are at most 1000 cities, numbered from 1. This is followed by R lines each containing the city numbers of the cities connected by that road, the maximum height allowed on that road, and the length of that road. The maximum height for each road is a positive integer, except that a height of -1 indicates that there is no height limit on that road. The length of each road is a positive integer at most 1000. Every road can be travelled in both directions, and there is at most one road connecting each distinct pair of cities. Finally, the last line of each case consists of the start and end city numbers, as well as the height limit (a positive integer) of the cargo truck. The input terminates when C = R = 0.

Output

For each case, print the case number followed by the maximum height of the cargo truck allowed and the length of the shortest route. Use the format as shown in the sample output. If it is not possible to reach the end city from the start city, print "cannot reach destination" after the case number. Print a blank line between the output of the cases.

Sample Input

5 6

1 2 7 5

1 3 4 2

2 4 -1 10

2 5 2 4

3 4 10 1

4 5 8 5

1 5 10

5 6

1 2 7 5

1 3 4 2

2 4 -1 10

2 5 2 4

3 4 10 1

4 5 8 5

1 5 4

3 1

1 2 -1 100

1 3 10

0 0

Sample Output

Case 1:

maximum height = 7

length of shortest route = 20

 

Case 2:

maximum height = 4

length of shortest route = 8

 

Case 3:

cannot reach destination

Source

2008 Rocky Mountain Regional

 

题目大意:有n个点,m条无向边,每一条边都有四个元素,x,y,h,w,分别表示起点,终点,限制高度和权值,最后一行输入三个元素s,t,h,分别表示起点终点和货物最大高度。问在最大高度能够从起点到达终点的最短路。

 

思路:

1、首先,如果起点的货物高度一旦确定了,那么一整条路上的货物高度就确定了, 所以这个货物起始高度是一个需要枚举的量,而其最短路径,就是SPFA要求的量,其中枚举量在变,dis【t】在变,我们要找到的最大枚举量的dis【t】。


2、显然,如果直接从h枚举到最大货物高度是需要很多次SPFA求最短路的,显然会T,这个时候需要我们优化枚举算法,使用二分查找的方法降低时间复杂度。


3、枚举最大高度的同时,记录可行解。(在二分的时候,最终的mid不一定就是最终解,要在二分的过程中记录最后可行解。)


4、注意输出格式。


AC代码:


#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
int head[100000];
struct EdgeNode
{
    int to;
    int h;
    int w;
    int next;
}e[1000000];
int dis[100000];
int vis[100000];
int n,m,cont,kase;
int ss,t,limith;
void add(int from,int to,int high,int w)
{
    e[cont].to=to;
    e[cont].w=w;
    e[cont].h=high;
    e[cont].next=head[from];
    head[from]=cont++;
}
int SPFA(int mid)
{
   // printf("%d\n",mid);
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)dis[i]=0x3f3f3f3f;
    dis[ss]=0;
    queue<int >s;
    s.push(ss);
    vis[ss]=1;
    while(!s.empty())
    {
        int u=s.front();
        s.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            int w=e[i].w;
            int h=e[i].h;
            if(dis[v]>dis[u]+w)
            {
                if(h==-1||h>=mid)
                {
                    dis[v]=dis[u]+w;
                    if(vis[v]==0)
                    {
                        vis[v]=1;
                        s.push(v);
                    }
                }
            }
        }
    }
    if(dis[t]>=0x3f3f3f3f)return 0;
    else return 1;
}
void erfen()
{
    int l=0;
    int r=limith;
    int mid;
    int ans=-1;
    int ans2;
    while(r-l>=0)
    {
        mid=(l+r)/2;
        if(SPFA(mid)==0)
        {
            r=mid-1;
        }
        else
        {
            l=mid+1;
            ans=mid;
            ans2=dis[t];
        }
    }
    printf("Case %d:\n",++kase);
    if(r==-1||ans==-1)
    printf("cannot reach destination\n");
    else
    {
        printf("maximum height = %d\n",ans);
        printf("length of shortest route = %d\n",ans2);
    }
}
int main()
{
    kase=0;
    while(~scanf("%d%d",&n,&m))
    {
        cont=0;
        memset(head,-1,sizeof(head));
        if(n+m==0)break;
        if(kase!=0)printf("\n");
        for(int i=0;i<m;i++)
        {
            int x,y,high,w;
            scanf("%d%d%d%d",&x,&y,&high,&w);
            add(x,y,high,w);
            add(y,x,high,w);
        }
        scanf("%d%d%d",&ss,&t,&limith);
        erfen();
    }
}
/*
5 5
1 2 -1 5
1 3 -1 2
2 4 -1 10
2 5 -1 4
3 4 -1 1
1 5 100
*/




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值