#include <bits/stdc++.h>
using namespace std;
#define forsn(i, s, n) for (int i = int(s); i < int(n); i++)
#define forn(i, n) forsn(i, 0, n)
#define dforsn(i, s, n) for (int i = int(n) - 1; i >= int(s); i--)
#define dforn(i, n) dforsn(i, 0, n)
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
using ll = long long;
using ld = long double;
using vi = vector<int>;
using vb = vector<bool>;
using vll = vector<ll>;
using ii = pair<int, int>;
using iii = tuple<int, int, int>;
#define fst first
#define snd second
#define pb push_back
#define eb emplace_back
const ll INF = 1e18;
struct Edge {
int u, v, c;
ll p;
};
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int n, m;
cin >> n >> m;
vector<Edge> graph(m);
vector<vector<tuple<int, int, ll>>> adj(n);
vector<map<int, ll>> sum(n);
for (auto &[u, v, c, p] : graph) {
cin >> u >> v >> c >> p;
--u, --v;
sum[u][c] += p;
sum[v][c] += p;
adj[u].eb(c, v, p);
adj[v].eb(c, u, p);
}
forn(u, n) {
sort(all(adj[u]));
}
vector<vll> dist(n);
forn(u, n) dist[u].assign(sz(adj[u]) + 1, INF);
priority_queue<tuple<ll, int, int>> pq;
auto PUSH = [&](int u, int s, ll d) {
if (d < dist[u][s]) {
dist[u][s] = d;
pq.emplace(-dist[u][s], u, s);
}
};
auto pos = [&](int u, iii e) {
return int(lower_bound(all(adj[u]), e) - begin(adj[u]));
};
PUSH(0, sz(adj[0]), 0LL);
while (!pq.empty()) {
auto [d, u, s] = pq.top();
pq.pop(); d *= -1;
if (dist[u][s] != d) continue;
int k = sz(adj[u]);
if (s != k) {
PUSH(u, k, d);
auto [color, _, cost] = adj[u][s];
int lo = pos(u, iii{color, 0, 0});
int hi = pos(u, iii{color + 1, 0, 0});
forsn(id, lo, hi) if (id != s) {
auto [c, v, p] = adj[u][id];
bool prv = id >= 1 && get<0>(adj[u][id - 1]) == c;
bool nxt = id + 1 < k && get<0>(adj[u][id + 1]) == c;
PUSH(v, pos(v, iii{c, u, p}), d + min(p, sum[u][c] - p - cost) * (prv || nxt));
}
} else {
forn(id, k) {
auto [c, v, p] = adj[u][id];
bool prv = id >= 1 && get<0>(adj[u][id - 1]) == c;
bool nxt = id + 1 < k && get<0>(adj[u][id + 1]) == c;
PUSH(v, pos(v, iii{c, u, p}), d + min(p, sum[u][c] - p) * (prv || nxt));
}
}
}
if (dist[n - 1][sz(adj[n - 1])] == INF) cout << "-1\n";
else cout << dist[n - 1][sz(adj[n - 1])] << '\n';
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |