hdu1839Delay Constrained Maximum Capacity Path(二分 + spfa)

题意:给出n个点,m条边,t  后跟m条边。

x, y, d, t    x y 表示边的顶点,d 表示这条边可以运输的最大容量,t表示用的时间。

问从1 运到n 的最大容量,1 到n的最大容量为1到n这条路径上容量最小的那个边的容量。但这条边上所用的所有时间和不能大于给出的总时间 t 。


思路:当有两个边量同时变化时,由于时间问题我们无法枚举各变量,此时好的做法是先二分一个变量的值,去枚举另外一个变量,就是本题要用的 二分 + spfa算法;

开始我用的是二分+Dijstra算法,超时了,还是spfa快啊

#include <iostream>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>

using namespace std;

const int inf = 99999999;
const int M = 10006;
struct node {

    int to;
    int time;
    int len;

};


node cur;
int ans;
int dist[M];
int n, m, t;
int maxn, minn;
vector<node>road[M];

void init(){

    maxn = 0;
    minn = inf;
    for(int i = 0; i <= n; i++)
        road[i].clear();
}

void input() {

    int x, y, d, time;

    for(int i = 0; i < m; i++){

        scanf("%d%d%d%d", &x, &y, &d, &time);
            cur.to = y;
            cur.len = d;
            cur.time = time;
            road[x].push_back(cur);  //建立双向边;
            cur.to = x;
            road[y].push_back(cur);
        maxn = max(maxn, d);
        minn = min(minn, d);
    }
}


bool spfa(int mid){

    int cnt;
    int dist[M], vist[M];
    queue<int>que;
    for(int i = 0; i <= n; i++){

        dist[i] = inf;
        vist[i] = 0;
    }

    vist[1] = 1;
    dist[1] = 0;
    que.push(1);
    while(!que.empty()){

        cnt = que.front();
        que.pop();
        vist[cnt] = 0;
        for(int i = 0; i < (int)road[cnt].size(); i++){

            cur = road[cnt][i];
            if(dist[cur.to] > dist[cnt] + cur.time && cur.len >= mid && dist[cnt] + cur.time <= t){

                dist[cur.to] = dist[cnt] + cur.time;
                if(!vist[cur.to]){

                    vist[cur.to] = 1;
                    que.push(cur.to);
                }
            }
        }
    }
    if(dist[n] != inf)
        return true;
    else
        return false;
}

void work(){
   // printf("%d  %d\n", maxn, minn);
    while(minn <= maxn){  //二分容量值;


        int mid = (maxn + minn)/2;
        //printf("%d\n", mid);
        if(spfa(mid)){

            ans = mid;
            minn = mid + 1;
        }else {

            maxn = mid -1;
        }
    }
    printf("%d\n", ans);
}

int main()
{
    int Case;
    scanf("%d", &Case);
    while(Case--){

        scanf("%d%d%d", &n, &m, &t);
        init();
        input();
        work();
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值