P1951 收費站_NOI導刊2009提高(2)
阿新 • • 發佈:2018-11-01
二分答案+dijkstra
這道題有被改編的另一道題:“通往奧格瑞瑪的道路”,相信你也做過吧。。。
看到“交的費用中最多的一次最少是多少”,就應該想到二分答案了。
所以我們二分費用,判斷最多的費用是一個\(mid\)的時候可不可以成功到達終點。
如何判斷能否成功到達終點?
不要說用SPFA!因為……被卡了。
我們用不被卡的dijkstra的堆優化就可以了。反正又沒有負權邊。
震驚!我這道題被卡了一段時間的原因居然是……
二分寫掛了!
眾所周知,二分答案差不多有兩種主流的寫法,一種兩個變數的,一種三個變數的。
兩個變數的可以實現,並且不容易錯。在while上面寫的條件是l < r
三個變數的實現必須是整數,如果是浮點數你就GG了。在while上的條件是l <= r
。我錯在了這個地方,就丟了一半的分!
所以好好寫二分哦!
程式碼:
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define ll long long const int maxn = 10005, maxm = 50005; const ll INF = 0x3f3f3f3f3f3f3f3f; struct Edges { ll next, to, weight; } e[maxm << 1]; ll head[maxn], tot; ll a[maxn], f[maxn]; ll dist[maxn]; ll n, m, s, t, c; struct Heapnodes { ll d, u; bool operator < (const Heapnodes &rhs) const { return d > rhs.d; } }; ll read() { ll ans = 0, s = 1; char ch = getchar(); while(ch > '9' || ch < '0'){ if(ch == '-') s = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0', ch = getchar(); return s * ans; } void link(ll u, ll v, ll w) { e[++tot] = (Edges){head[u], v, w}; head[u] = tot; } bool check(ll mid) { memset(dist, 0x3f, sizeof dist); std::priority_queue<Heapnodes> heap; dist[s] = 0; heap.push((Heapnodes){dist[s], s}); while(!heap.empty()) { Heapnodes x = heap.top(); heap.pop(); int d = x.d, u = x.u; if(d != dist[u]) continue; if(f[u] > mid) continue; for(ll i = head[u]; i; i = e[i].next) { ll v = e[i].to; if(f[v] > mid) continue; if(dist[u] + e[i].weight < dist[v]) { dist[v] = dist[u] + e[i].weight; heap.push((Heapnodes){dist[v], v}); } } } return dist[t] <= c; } int main() { n = read(), m = read(), s = read(), t = read(), c = read(); for(int i = 1; i <= n; i++) { a[i] = f[i] = read(); } while(m--) { ll x = read(), y = read(), z = read(); link(x, y, z); link(y, x, z); } if(!check(INF)) { printf("-1\n"); return 0; } std::sort(a + 1, a + n + 1); ll left = 1, right = n, ans = -1; while(left <= right)// !!!! { ll mid = (left + right) >> 1; if(check(a[mid])) ans = a[mid], right = mid - 1; else left = mid + 1; } printf("%lld\n", ans); return 0; }