1. 程式人生 > >NEERC17 J Journey from Petersburg to Moscow

NEERC17 J Journey from Petersburg to Moscow

top inline ORC src names get div lld 技術分享

CF上可以提交。 鏈接

依然是很妙的解法。

我們可以枚舉每一個出現過的邊權$L$,然後把所有邊的邊權減掉這個$L$,如果小於$L$就變為$0$,然後跑一遍最短路然後加上$k * L$更新答案即可。

註意$L$也可以取到$0$。

這樣做就是強制讓出了前$k$大的邊的邊權,所以能計算到所有答案。

時間復雜度$O(n^2logn)$。

Code:

技術分享圖片
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#include <algorithm>
using
namespace std; typedef long long ll; typedef pair <ll, int> pin; const int N = 3005; const ll inf = 0x3f3f3f3f3f3f3f3f; int n, m, K, vCnt = 0, tot = 0, head[N]; ll eVal[N], dis[N]; bool vis[N]; struct Edge { int to, nxt; ll val; } e[N << 1]; inline void add(int from
, int to, ll val) { e[++tot].to = to; e[tot].val = val; e[tot].nxt = head[from]; head[from] = tot; } template <typename T> inline void read(T &X) { X = 0; char ch = 0; T op = 1; for(; ch > 9 || ch < 0; ch = getchar()) if(ch == -) op = -1
; for(; ch >= 0 && ch <= 9; ch = getchar()) X = (X << 3) + (X << 1) + ch - 48; X *= op; } inline ll max(ll x, ll y) { return x > y ? x : y; } template <typename T> inline void chkMin(T &x, T y) { if(y < x) x = y; } priority_queue <pin> Q; void dij(ll nowL) { memset(dis, 0x3f, sizeof(dis)); memset(vis, 0, sizeof(vis)); Q.push(pin(dis[1] = 0LL, 1)); for(; !Q.empty(); ) { int x = Q.top().second; Q.pop(); if(vis[x]) continue; vis[x] = 1; for(int i = head[x]; i; i = e[i].nxt) { int y = e[i].to; ll val = max(0LL, e[i].val - nowL) + dis[x]; if(val < dis[y]) { dis[y] = val; Q.push(pin(-dis[y], y)); } } } } int main() { read(n), read(m), read(K); for(int i = 1; i <= m; i++) { int x, y; ll v; read(x), read(y), read(v); add(x, y, v), add(y, x, v); eVal[++vCnt] = v; } eVal[++vCnt] = 0LL; sort(eVal + 1, eVal + 1 + vCnt); vCnt = unique(eVal + 1, eVal + 1 + vCnt) - eVal - 1; ll ans = inf; for(int i = 1; i <= vCnt; i++) { dij(eVal[i]); chkMin(ans, dis[n] + 1LL * K * eVal[i]); } printf("%lld\n", ans); return 0; }
View Code

NEERC17 J Journey from Petersburg to Moscow