zoukankan      html  css  js  c++  java
  • [洛谷P1951]收费站_NOI导刊2009提高(2)

    题目大意:有一张$n$个点$m$条边的图,每个点有一个权值$w_i$,有边权,询问从$S$到$T$的路径中,边权和小于$s$,且$maxlimits_{路径经过k}{w_i}$最小,输出这个最小值,若到达不了,输出$-1$

    题解:看到最大值最小,想到二分答案,二分这个最大值,每次对这个二分的答案跑一遍最短路,看是否可以到达就行了

    卡点:1.没有判断起点的权值大于二分答案的情况

    C++ Code:

    #include <cstdio>
    #include <algorithm>
    #include <ext/pb_ds/priority_queue.hpp>
    #define maxn 10010
    #define maxm 50010
    using namespace std;
    const long long inf = 0x3f3f3f3f3f3f3f3f;
    int n, m, S, T, s, ans = -1;
    int f[maxn], rnk[maxn];
    
    inline bool cmp(int a, int b) {return f[a] < f[b];}
    
    int head[maxn], cnt;
    struct Edge {
    	int to, nxt, w;
    } e[maxm << 1];
    void add(int a, int b, int c) {
    	e[++cnt] = (Edge) {b, head[a], c}; head[a] = cnt;
    }
    
    long long d[maxn];
    struct cmpq {
    	inline bool operator () (const int &a, const int &b) const {
    		return d[a] > d[b];
    	}
    };
    __gnu_pbds::priority_queue<int, cmpq> q;
    __gnu_pbds::priority_queue<int, cmpq>::point_iterator iter[maxn];
    bool check(int mid) {
    	if (f[S] > mid) return false;
    	while (!q.empty()) q.pop();
    	for (int i = 1; i <= n; i++) d[i] = inf, iter[i] = q.push(i);
    	d[S] = 0;
    	q.modify(iter[S], S);
    	while (!q.empty()) {
    		int u = q.top(); q.pop();
    		for (int i = head[u]; i; i = e[i].nxt) {
    			int v = e[i].to;
    			if (f[v] > mid) continue;
    			if (d[v] > d[u] + e[i].w) {
    				d[v] = d[u] + e[i].w;
    				if (d[T] <= s) return true;
    				q.modify(iter[v], v);
    			}
    		}
    	}
    	return d[T] <= s;
    }
    int main() {
    	scanf("%d%d%d%d%d", &n, &m, &S, &T, &s);
    	for (int i = 1; i <= n; i++) scanf("%d", &f[i]), rnk[i] = i;
    	for (int i = 1; i <= m; i++) {
    		int a, b, c;
    		scanf("%d%d%d", &a, &b, &c);
    		if (a == b) continue;
    		add(a, b, c);
    		add(b, a, c);
    	}
    	sort(rnk + 1, rnk + n + 1, cmp);
    	int L = 1, R = n;
    	while (L <= R) {
    		int mid = L + R >> 1;
    		if (check(f[rnk[mid]])) {
    			ans = mid;
    			R = mid - 1;
    		} else L = mid + 1;
    	}
    	if (~ans) printf("%d
    ", f[rnk[ans]]);
    	else puts("-1");
    	return 0;
    } 
    
  • 相关阅读:
    DIY 作品 及 维修 不定时更新
    置顶,博客中所有源码 github
    openwrt PandoraBox PBR-M1 极路由4 HC5962 更新固件
    使用 squid 共享 虚拟专用网至局域网
    第一次参加日语能力测试 N5
    libx264 libfdk_aac 编码 解码 详解
    开发RTSP 直播软件 H264 AAC 编码 live555 ffmpeg
    MFC Camera 摄像头预览 拍照
    http2 技术整理 nginx 搭建 http2 wireshark 抓包分析 server push 服务端推送
    plist 图集 php 批量提取 PS 一个个切
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9498773.html
Copyright © 2011-2022 走看看