Codeforces 1486E Paired Payment

https://codeforces.ml/problemset/problem/1486/E

题意:一张 n 个点 m 条边无向图带边权,1 是起点,每次走一步需要从当前点走两步,花费是两条边的和的平方,求 1 到达所有其他点的最短路,如果无法到达某些点输出 -1。

数据范围:$ 2 \leq n \leq 10^5 $, $ 1 \leq m \leq min(\frac{n \cdot (n - 1)}{2}, 2 \cdot 10^5)$,最大边权 50

题解:看到边权数据范围就知道是一个显然的分层图模型,主要是想记录一下比较容易理解的一种实现方式。

不用显性建分层图,直接保存原图,将分层图模型中的 dist 数据分为每个点 51 个结果,然后中间判断 pre 是哪个结果出来的即可。

/*================================================================
*
*   创 建 者: badcw
*   创建日期: 2021/3/9 11:42 下午
*
================================================================*/
#include <bits/stdc++.h>

#define VI vector<int>
#define ll long long
#define dbg1(x) cerr<<#x<<"="<<(x)<<" "
#define dbg2(x) cerr<<#x<<"="<<(x)<<"\n"
using namespace std;

namespace IO {
    template<class T>
    void _R(T &x) { cin >> x; }
    void _R(int &x) { scanf("%d", &x); }
    void _R(ll &x) { scanf("%lld", &x); }
    void _R(double &x) { scanf("%lf", &x); }
    void _R(char &x) { x = getchar(); }
    void _R(char *x) { scanf("%s", x); }
    void R() {}
    template<class T, class... U>
    void R(T &head, U &... tail) { _R(head), R(tail...); }
    template<class T>
    void _W(const T &x) { cout << x; }
    void _W(const int &x) { printf("%d", x); }
    void _W(const ll &x) { printf("%lld", x); }
    void _W(const double &x) { printf("%.16f", x); }
    void _W(const char &x) { putchar(x); }
    void _W(const char *x) { printf("%s", x); }
    template<class T, class U>
    void _W(const pair<T, U> &x) { _W(x.first), putchar(' '), _W(x.second); }
    template<class T>
    void _W(const vector<T> &x) { for (auto i = x.begin(); i != x.end(); _W(*i++)) if (i != x.cbegin()) putchar(' '); }
    void W() {}
    template<class T, class... U>
    void W(const T &head, const U &... tail) { _W(head), putchar(sizeof...(tail) ? ' ' : '\n'), W(tail...); }
}
using namespace IO;


const int maxn = 1e5 + 50;
const int mod = 1e9 + 7;

ll qp(ll a, ll n) {
    ll res = 1;
    n %= mod - 1;
    if (n < 0) n += mod - 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return res;
}

ll qp(ll a, ll n, int mod) {
    ll res = 1;
    n %= mod - 1;
    if (n < 0) n += mod - 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return res;
}

int dist[maxn][55];
int n, m;
vector<pair<int, int> > edge[maxn];

struct node {
    int u, val, pre;
    bool operator<(const node &oth) const {
        return val > oth.val;
    }
};

int main(int argc, char *argv[]) {
    R(n, m);
    for (int i = 0; i < m; ++i) {
        int u, v, w;
        R(u, v, w);
        edge[u].emplace_back(v, w);
        edge[v].emplace_back(u, w);
    }
    memset(dist, -1, sizeof dist);
    priority_queue<node> qu;
    dist[1][0] = 0;
    qu.push({1, 0, 0});
    while (!qu.empty()) {
        node tmp = qu.top();
        qu.pop();
        int u = tmp.u;
        if (dist[u][tmp.pre] != tmp.val) continue;
        if (tmp.pre == 0) {
            for (auto &it : edge[u]) {
                int v = it.first;
                int w = it.second;
                if (dist[v][w] == -1 || dist[v][w] > tmp.val) {
                    dist[v][w] = tmp.val;
                    qu.push({v, tmp.val, w});
                }
            }
        } else {
            for (auto &it : edge[u]) {
                int v = it.first;
                int w = tmp.val + (tmp.pre + it.second) * (tmp.pre + it.second);
                if (dist[v][0] == -1 || dist[v][0] > w) {
                    dist[v][0] = w;
                    qu.push({v, w, 0});
                }
            }
        }
    }
    for (int i = 1; i <= n; ++i) printf("%d%c", dist[i][0], " \n"[i == n]);
    return 0;
}
posted @ 2021-03-10 00:01  badcw  阅读(88)  评论(0编辑  收藏  举报