BZOJ 1375: [Baltic2002]Bicriterial routing 双调路径 SPFA+DP思想

Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 513 Solved: 189

Description

来越多,因此选择最佳路径是很现实的问题。城市的道路是双向的,每条道路有固定的旅行时间以及需要支付的费用。路径由连续的道路组成。总时间是各条道路旅行时间的和,总费用是各条道路所支付费用的总和。同样的出发地和目的地,如果路径A比路径B所需时间少且费用低,那么我们说路径A比路径B好。对于某条路径,如果没有其他路径比它好,那么该路径被称为最优双调路径。这样的路径可能不止一条,或者说根本不存在。 给出城市交通网的描述信息,起始点和终点城市,求最优双条路径的条数。城市不超过100个,边数不超过300,每条边上的费用和时间都不超过100。

Input

第一行给出有多少个点,多少条边,开始点及结束点. 下面的数据用于描述这个地图

Output

有多少条最优双调路径

Sample Input

4 5 1 4

2 1 2 1

3 4 3 1

2 3 1 2

3 1 1 4

2 4 2 4

Sample Output

2
HINT
这里写图片描述

Source


因为要满足条件的话,必须要在两个值中有个值是所有值中最小的,或者说满足大于某个值的其他组的另一个值都小于他,那么我们就可以搞一个DP数组,dp[i][j]表示从起点开始走到i点,花费时间最少为j的时候道路费用最少为dp[i][j],然后最后我们for一遍就可以了,因为dp[T][i]中,for的时候i是具有单调性的


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN = 106;
const int MAXM = 606;
const int up = 10000;
int n, m, head[MAXN], tail, dis[MAXN][ MAXN * MAXN ], inf, S, T;

struct Line{ int to, nxt, flow, tim; }line[ MAXM * 2 ];
bool vis[MAXN][ MAXN * MAXN ];
void add_line( int from, int to, int flow, int tim ) {
    line[++tail].nxt = head[from]; line[tail].to = to; line[tail].tim = tim;
    line[tail].flow = flow; head[from] = tail;
}
queue<pair<int,int> > q;
void SPFA( ) {
    memset( dis, 0x3f, sizeof( dis ) );
    memset( vis, false, sizeof( vis ) );
    inf = dis[0][0];
    q.push( make_pair( S, 0 ) );
    dis[S][0] = 0; vis[S][0] = true;
    while( !q.empty() ) {
        pair< int, int > tmp = q.front(); q.pop();
        int u = tmp.first; int flowu = tmp.second; vis[u][flowu] = false;
        for( register int i = head[u]; i; i = line[i].nxt ) {
            int v = line[i].to;
            int flowv = flowu + line[i].flow;
            if( flowv <= up ) {
                if( dis[v][flowv] > dis[u][flowu] + line[i].tim ) {
                    dis[v][flowv] = dis[u][flowu] + line[i].tim;
                    if( vis[v][flowv] ) continue;
                    q.push( make_pair( v, flowv ) ); 
                    vis[v][flowv] = true;
                }
            }
        }
    }
}
int main( ) {
    scanf( "%d%d%d%d", &n, &m, &S, &T );
    for( register int i = 1; i <= m; i++ ) { int ff, tt, ww, ti;
        scanf( "%d%d%d%d", &ff, &tt, &ww, &ti );
        add_line( ff, tt, ww, ti );
        add_line( tt, ff, ww, ti );
    }
    SPFA();
    int minn = inf; int cnt = 0;
    for( register int i = 0; i <= up; i++ ) {
        if( dis[T][i] < minn ) {
            minn = dis[T][i];
            cnt++;
        }
    }
    printf( "%d\n", cnt );
    return 0;
}

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值