双调路径

双调路径

思路:我们可以容易想到,通过不同的边到达某个点的时间和金钱是不一样的,这是难点。我们发现点数n = 100,权值t,c = 100,如果我们分别维护时间权值为x时,到达该城市的最少金钱是多少,即d[城市][时间]  = 金钱,因为 n = 100, t,c = 100,说明我们需要维护 n*t 个点的值,则边数为 n * t * m = 3e6,我们可以用spfa解决。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>

using namespace std;

#define ll long long
#define pb push_back
#define fi first
#define se second

const int INF = 2e4;

struct node {
    int v, c, t;
};

void SPFA(int n, int S, int T, vector<vector<node> >& E) {
    int _size = n * 100;
    vector<vector<bool> > vis(n + 1, vector<bool>(_size + 100, 0));
    vector<vector<int> > d(n + 1, vector<int>(_size + 100, INF));
    queue<pair<int, int> > que;
    vis[S][0] = true;
    d[S][0] = 0;
    que.push(make_pair(S, 0));

    while (!que.empty()) {
        int u = que.front().fi;
        int w = que.front().se;
        que.pop();
        vis[u][w] = false;
        for (auto e : E[u]) {
            if (w + e.t > n * 100)
                continue;  //最多 n * 100 的时间消耗,没有限制,则d[x][∞]会一直更新
            if (d[e.v][w + e.t] > d[u][w] + e.c) {
                d[e.v][w + e.t] = d[u][w] + e.c;
                if (!vis[e.v][w + e.t]) {
                    vis[e.v][w + e.t] = true;
                    que.push(make_pair(e.v, w + e.t));
                }
            }
        }
    }
    int ans = 0;
    int Min = INF;
    for (int i = 0; i <= n * 100; ++i) {
        if (d[T][i] < Min) {
            ++ans;
            Min = d[T][i];
        }
    }
    printf("%d\n", ans);
    // cout << "this" << endl;
}

void solve() {
    int n, m, S, T;
    scanf("%d%d%d%d", &n, &m, &S, &T);
    vector<vector<node> > E(n + 1);
    int u, v, c, t;
    for (int i = 0; i < m; ++i) {
        scanf("%d%d%d%d", &u, &v, &c, &t);
        E[u].pb({ v, c, t });
        E[v].pb({ u, c, t });
    }

    SPFA(n, S, T, E);
}

int main() {
    // ios::sync_with_stdio(false);
    // cin.tie(0); cout.tie(0);
    // freopen("C:\\Users\\admin\\Desktop\\input.txt", "r", stdin);
    // freopen("C:\\Users\\admin\\Desktop\\output.txt", "w", stdout);
    solve();
    // cout << "not error" << endl;
    return 0;
}

 

posted @ 2020-05-23 21:07  SummerMingQAQ  阅读(329)  评论(0编辑  收藏  举报