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;
}