Telephone Lines 通信线路(二分+最短路)

8 篇文章 0 订阅
2 篇文章 0 订阅

 原题:

Description

Farmer John wants to set up a telephone line at his farm. Unfortunately, the phone company is uncooperative, so he needs to pay for some of the cables required to connect his farm to the phone system.

There are N (1 ≤ N ≤ 1,000) forlorn telephone poles conveniently numbered 1..N that are scattered around Farmer John's property; no cables connect any them. A total of P (1 ≤ P ≤ 10,000) pairs of poles can be connected by a cable; the rest are too far apart.

The i-th cable can connect the two distinct poles Ai and Bi, with length Li (1 ≤ Li ≤ 1,000,000) units if used. The input data set never names any {AiBi} pair more than once. Pole 1 is already connected to the phone system, and pole N is at the farm. Poles 1 and N need to be connected by a path of cables; the rest of the poles might be used or might not be used.

As it turns out, the phone company is willing to provide Farmer John with K (0 ≤ K < N) lengths of cable for free. Beyond that he will have to pay a price equal to the length of the longest remaining cable he requires (each pair of poles is connected with a separate cable), or 0 if he does not need any additional cables.

Determine the minimum amount that Farmer John must pay.

Input

* Line 1: Three space-separated integers: NP, and K

* Lines 2..P+1: Line i+1 contains the three space-separated integers: AiBi, and Li

Output

Line 1: A single integer, the minimum amount Farmer John can pay. If it is impossible to connect the farm to the phone company, print -1.

Sample Input

5 7 1
1 2 5
3 1 4
2 4 8
3 2 3
5 2 9
3 4 7
4 5 6

Sample Output

4

翻译: 

Description

在郊区有 N 座通信基站,P 条 双向 电缆,第 i 条电缆连接基站 Ai 和 Bi 。

特别地,1 号基站是通信公司的总站,N 号基站位于一座农场中。

现在,农场主希望对通信线路进行升级,其中升级第 i 条电缆需要花费 Li 。

电话公司正在举行优惠活动。

农产主可以指定一条从 1 号基站到 N 号基站的路径,并指定路径上不超过 K 条电缆,由电话公司免费提供升级服务。

农场主只需要支付在该路径上剩余的电缆中,升级价格最贵的那条电缆的花费即可。

求至少用多少钱可以完成升级。

Input

第 1 行:三个整数 N , P , K  ( 0 ≤ K < N ≤ 1000 ,  1 ≤ P ≤ 10000 ) 。

第 2 .. P + 1 行:第 i + 1 行包含三个整数 Ai , Bi , Li  ( 1 ≤ Li ≤ 1000000 ) 。

Output

一个整数,表示最少花费。

若 1 号基站与 N 号基站之间不存在路径,则输出 −1

Sample Input

5 7 1
1 2 5
3 1 4
2 4 8
3 2 3
5 2 9
3 4 7
4 5 6

Sample Output

4

获取题意:题目要求找出 “点1到点n的所有路径上第k+1大的边的长度” 的最小值,如果点1无法到达点n则输出-1,如果存在点1到达点n的路径的边的数量<=k则输出0

思路: 一般求 最大最小值 或 最小最大值 可以联系二分算法。

在二分算法中,一般存在某个特性,使得以答案值为分界点,一边满足该特性,另一边不满足该特性

设dist[i]表示“在点1到点n的各路径中长度大于i的边数的最小数量”
首先假设答案为ans,则ans满足 dist[ans]=k
设x > ans,长度变大,大于x的边可能会变少,因此dist[x]<=k
设y < ans,长度变小,大于y的边一定会变多,因此dist[y]>k
于是一边满足dist[i]<=k,一边不满足,因此可以以此条件作为该二分的特性

赋下图方便理解

如何实现dist[i]:将大于i的边权视为1,小于i的边权视为0,跑一遍dijkstra求最短路即可
考虑答案为0和-1的情况:令l=0,r=1e6+1即可 

完整代码如下:

#include<bits/stdc++.h>
using namespace std;

const int N = 1200, M = 10200;
int h[N], e[2 * M], w[2 * M], ne[2 * M], idx;
void add(int a, int b, int c) {
	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

int n, p, k;
int dist[N], st[N];

bool check(int x) {
	memset(dist, 0x3f, sizeof dist);
	memset(st, 0, sizeof st);
	dist[1] = 0;
	deque<int>q;
	q.push_front(x);

	while (q.size()) {
		int t = q.front();
		q.pop_front();

		if (st[t])continue;
		else st[t] = 1;

		if (t == n)break;
		for (int i = h[t]; i != -1; i = ne[i]) {
			int j = e[i];
			if (dist[j] > dist[t] + w[i] > x ? 1 : 0) {
				dist[j] = dist[t] + w[i] > x ? 1 : 0;
				if (w[i] > x)q.push_back(j);
				else q.push_front(j);
			}
		}
	}
	
	return dist[n] <= k;

}

int main() {
	memset(h, -1, sizeof h);
	scanf("%d%d%d", &n, &p, &k);
	int a, b, c;
	for (int i = 0; i < p; i++) {
		scanf("%d%d%d", &a, &b, &c);
		add(a, b, c);
		add(b, a, c);
	}

int r = 0, l = 1e6 + 1;
while (l < r) {
	int mid = (r + l) / 2;
	if (check(mid))r = mid;
	else l = mid + 1;
}

	if (r == 1e6 + 1)printf("-1\n");
	else printf("%d\n", r);

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值