zoukankan      html  css  js  c++  java
  • P1948 [USACO08JAN]Telephone Lines S

    P1948 [USACO08JAN]Telephone Lines S

    这种题显然考虑二分(有条件最大值最小(确信)。

    然后发现可以二分,那么直接二分跑dijk/spfa/0-1bfs。

    为啥啊,因为,肯定是要选够 (K) 条的。所以我们二分一下第 (K-1) 条边长。大于的都设 (1) 小于等于的都设 (0)。分别代表需要一个代价去免费它或者需要自己付款。

    然后就是答案了。

    /*
    	Name:
    	Author: Gensokyo_Alice
    	Date:
    	Description:
    */
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <ctime>
    #include <map>
    #include <set>
    
    using namespace std;
    
    typedef long long ll;
    const ll MAXN = 1e6+10, INF = 0x3f3f3f3f3f3f3f3f;
    
    ll head[MAXN], cnt = -1, N, M, KK, hd[MAXN], ck = -1, dis[MAXN], vis[MAXN];
    
    struct edge {
    	ll nt, to, v;
    } E[MAXN], K[MAXN];
    
    struct heap {
    	ll now, val;
    	heap(){}
    	heap(ll _now, ll _val): now(_now), val(_val) {}
    	friend bool operator < (heap a, heap b) {return a.val > b.val;}
    };
    
    void add_K(ll, ll, ll);
    void add(ll, ll, ll);
    ll check(ll);
    
    int main() {
    	memset(hd, -1, sizeof(hd));
    	scanf("%lld%lld%lld", &N, &M, &KK);
    	for (ll i = 1, x, y, v; i <= M; i++) {
    		scanf("%lld%lld%lld", &x, &y, &v);
    		add_K(x, y, v);
    		add_K(y, x, v);
    	}
    	ll l = 0, r = MAXN, ans = -1;
    	while (l <= r) {
    		ll mid = (l + r) >> 1;
    		if (check(mid) <= KK) {
    			r = mid - 1;
    			ans = mid;
    		} else l = mid + 1;
    	}
    	printf("%lld", ans);
        return 0;
    }
    
    ll check(ll tem) {
    	for (ll i = 0; i < N + 10; i++) head[i] = -1;
    	for (ll i = 1; i <= N; i++) {
    		for (ll j = hd[i]; ~j; j = K[j].nt) {
    			ll v = K[j].to;
    			add(i, v, K[j].v > tem);
    		}
    	}
    	for (ll i = 0; i < N + 10; i++) dis[i] = INF, vis[i] = 0;
    	vis[1] = 1, dis[1] = 0;
    	priority_queue <heap> q;
    	q.push(heap(1, 0));
    	while (!q.empty()) {
    		heap nt = q.top(); q.pop();
    		if (nt.val > dis[nt.now]) continue;
    		for (ll i = head[nt.now]; ~i; i = E[i].nt) {
    			ll v = E[i].to;
    			if (dis[v] > dis[nt.now] + E[i].v) {
    				dis[v] = dis[nt.now] + E[i].v;
    				q.push(heap(v, dis[v]));
    			}
    		}
    	}
    	return dis[N];
    }
    
    void add(ll x, ll y, ll v) {
    	cnt++;
    	E[cnt].v = v;
    	E[cnt].to = y;
    	E[cnt].nt = head[x];
    	head[x] = cnt;
    }
    
    void add_K(ll x, ll y, ll v) {
    	ck++;
    	K[ck].v = v;
    	K[ck].to = y;
    	K[ck].nt = hd[x];
    	hd[x] = ck;
    }
    
    
  • 相关阅读:
    python3.6中 字典类型和字符串类型互相转换的方法
    "sorted()"中的"Key Functions"
    tuple unpacking
    理解"__repr__"
    Python中的"Special Method"
    abstractmethod
    JavaScript括号中什么什么不加引号什么时候加引号?
    加载网页时速度慢的一些知识点
    Login登录页面的制作流程(摘要)
    JavaScript总结1
  • 原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/13993298.html
Copyright © 2011-2022 走看看