hdu 2962 Trucking 二分 + Dijsktra

Dijsktra: 先找到一个与源点s相连最短路s--->k,然后通过 k 更新
与源点相连的点,


思路:先用二分不断逼近最高的高度下的最短路;
在确定一个高度时候,就开始用Dijskstra 去找是否存在最短的路
在求最短的路的时候,要判断路中的立交桥的高度要 >= 每次逼近的假设高度

不断进行这样的过程 最后二分将逼近一个值,使高度最大下的一个最短路;



#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int _max = 0x3f3f3f3f;
const int maxn = 1005;
int mp[maxn][maxn];
int hei[maxn][maxn];
int dist[maxn];
bool visit[maxn];
int pre[maxn];
int n, m, st, en, H, tt;

void inint()
{
    for(int i = 1; i <maxn; i++)
        for(int j = 1; j <maxn; j++)
        {
            mp[i][j] = _max;
            hei[i][j] = 0;
        }
}

void input()
{
    for(int i = 0; i < m; i++)
    {
        int u, v, h, w;
        scanf("%d%d%d%d", &u, &v, &h, &w);
        if(mp[u][v] > w) mp[u][v] = mp[v][u] = w;
        if(h == -1) hei[u][v] = hei[v][u] = _max;//
        else hei[u][v] = hei[v][u] = h;
    }
    scanf("%d%d%d", &st, &en, &H);
}

bool Dijsktra(int mid)
{
    int k;
    memset(visit, false, sizeof(visit));
    for(int i = 1; i <= n; i++)
    {
        if(hei[st][i] >= mid) dist[i] = mp[st][i];//
        else dist[i] = _max;
        pre[i]=st;//记录每个节点的前驱,方便比较立交桥是否大于mid;
    }
    dist[st] = 0;
    visit[st] = true;
    for(int i = 1; i < n; i++)
    {
        int _min = _max;
        for(int j = 1; j <= n; j++)
        {
            if(!visit[j] && dist[j] < _min && hei[pre[j]][j] >= mid)//判断立交桥是否满足
            {
                _min = dist[j];
                k = j;
            }
        }
        if(_min == _max) return false;//说明在mid这个高度值下没有;
        if(k == en) return true;//满足
        visit[k] = true;
        for(int j = 1; j <= n; j++)
        {
            if(!visit[j] && dist[j] > dist[k] + mp[k][j] && mp[k][j]!=_max  && hei[k][j] >= mid)//只需判断k--->j中立交桥是否满足
            {                                                                     //其他在之前的判断中一定满足;
                dist[j] = dist[k] + mp[k][j];
                pre[j] = k;
            }
        }
    }
    return false;
}

void jsuan()
{
    bool first;
    int l = 1;
    int r = H;
    int ans;
    while(r-l>=0)
    {
        int mid = (l+r)>>1;
        first = Dijsktra(mid);
        if(first)
        {
            l = mid+1;
            ans = dist[en];//要把计算的结果存在ans中 否则可能这次满足 下次就不满足 但dist[en],被初始化,的不到结果;
        }                  // 在这错了一下午。。。。。。。。。。。。。
        else r = mid-1;
    }
    if(tt > 0) printf("\n");
    printf("Case %d:\n", ++tt);
    if(r!=0)
    {
        printf("maximum height = %d\n", r);
        printf("length of shortest route = %d\n", ans);
    }
    else if(r==0)
        printf("cannot reach destination\n");
}

int main()
{
    tt=0;
    while(scanf("%d%d", &n, &m),(n+m))
    {
        inint();
        input();
        jsuan();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值