架设电话线

121 篇文章 2 订阅
78 篇文章 2 订阅

架设电话线 ⁡ \operatorname{架设电话线} 线

& ⁡ \operatorname{\&} &

Telephone Lines S ⁡ \operatorname{Telephone\ Lines\ S} Telephone Lines S

题目链接:

1. 架设电话线: SSL比赛 1466 ⁡ \operatorname{SSL比赛\ 1466} SSL 1466
2. Telephone Lines S: l u o g u   1948 luogu\ 1948 luogu 1948

架 设 电 话 线 : 架设电话线: 线

题目

Farmer John 打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务。于是, FJ 必须为此向电信公司支付一定的费用。

FJ 的农场周围分布着 N ( 1 < = N < = 1 , 000 ) N(1 <= N <= 1,000) N(1<=N<=1,000) 根按 1.. N 1..N 1..N 顺次编号的废弃的电话线杆,任意两根电话线杆间都没有电话线相连。一共 P ( 1 < = P < = 10 , 000 ) P(1 <= P <= 10,000) P(1<=P<=10,000) 对电话线杆间可以拉电话线,其余的那些由于隔得太远而无法被连接。第 i i i 对电话线杆的两个端点分别为 A i A_i Ai B i B_i Bi ,它们间的距离为 L i ( 1 < = L i < = 1 , 000 , 000 ) L_i (1 <= L_i <= 1,000,000) Li(1<=Li<=1,000,000) 。数据中保证每对 { A i , B i } \{A_i,B_i\} {AiBi} 最多只出现 1 1 1 次。编号为 1 1 1 的电话线杆已经接入了全国的电话网络,整个农场的电话线全都连到了编号为 N N N 的电话线杆上。也就是说, FJ 的任务仅仅是找一条将 1 1 1 号和 N N N 号电话线杆连起来的路径,其余的电话线杆并不一定要连入电话网络。

经过谈判,电信公司最终同意免费为 FJ 连结 K ( 0 < = K < N ) K(0 <= K < N) K(0<=K<N) 对由 FJ 指定的电话线杆。对于此外的那些电话线, FJ 需要为它们付的费用,等于其中最长的电话线的长度(每根电话线仅连结一对电话线杆)。如果需要连结的电话线杆不超过 K K K对 ,那么 F J FJ FJ 的总支出为 0 0 0

请你计算一下, FJ 最少需要在电话线上花多少钱。

样例解释(样例在下面)

输入解释

一共有 5 5 5 根废弃的电话线杆。电话线杆 1 1 1 不能直接与电话线杆 4 4 4 5 5 5 相连。电话线杆 5 5 5 不能直接与电话线杆 1 1 1 3 3 3 相连。其余所有电话线杆间均可拉电话线。电信公司可以免费为 FJ 连结一对电话线杆。

输出解释

FJ 选择如下的连结方案: 1 −  ⁣ ⁣ > 3 1-\!\!>3 1>3 3 −  ⁣ ⁣ > 2 3-\!\!>2 3>2 2 −  ⁣ ⁣ > 5 2-\!\!>5 2>5 ,这 3 3 3 对电话线杆间需要的电话线的长度分别为 4 4 4 3 3 3 9 9 9 。 FJ 让电信公司提供那条长度为 9 9 9 的电话线,于是,他所需要购买的电话线的最大长度为 4 4 4
数据点 1 ∼ 4 1\sim 4 14 N < = 10 , P < = 20 ; N<=10,P<=20; N<=10,P<=20;
数据点 5 ∼ 6 5\sim 6 56 N < = 50 , P < = 200 ; N<=50,P<=200; N<=50,P<=200;
数据点 7 ∼ 9 7\sim 9 79 N < = 1000 , P < = 1000 ; N<=1000,P<=1000; N<=1000,P<=1000;
数据点 10 ∼ 11 10\sim 11 1011 N < = 1000 , P < = 5000 ; N<=1000,P<=5000; N<=1000,P<=5000;
数据点 12 ∼ 13 12\sim 13 1213 N < = 1000 , P < = 10000 ; N<=1000,P<=10000; N<=1000,P<=10000;

T e l e p h o n e   L i n e s   S : Telephone\ Lines\ S: Telephone Lines S

题目

多年以后,笨笨长大了,成为了电话线布置师。由于地震使得某市的电话线全部损坏,笨笨是负责接到震中市的负责人。该市周围分布着 N ( 1 < = N < = 1000 ) N(1<=N<=1000) N(1<=N<=1000) 根据 1 … … n 1……n 1n 顺序编号的废弃的电话线杆,任意两根线杆之间没有电话线连接,一共有 p ( 1 < = p < = 10000 ) p(1<=p<=10000) p(1<=p<=10000) 对电话杆可以拉电话线。其他的由于地震使得无法连接。

i i i 对电线杆的两个端点分别是 a i , b i a_i,b_i ai,bi ,它们的距离为 l i ( 1 < = l i < = 1000000 ) l_i(1<=li<=1000000) li(1<=li<=1000000) 。数据中每对 ( a i , b i ) (a_i,b_i) (ai,bi) 只出现一次。编号为 1 1 1 的电话杆已经接入了全国的电话网络,整个市的电话线全都连到了编号 N N N 的电话线杆上。也就是说,笨笨的任务仅仅是找一条将 1 1 1 号和 N N N 号电线杆连起来的路径,其余的电话杆并不一定要连入电话网络。

电信公司决定支援灾区免费为此市连接 k k k 对由笨笨指定的电话线杆,对于此外的那些电话线,需要为它们付费,总费用决定于其中最长的电话线的长度(每根电话线仅连接一对电话线杆)。如果需要连接的电话线杆不超过 k k k 对,那么支出为 0. 0. 0.

请你计算一下,将电话线引导震中市最少需要在电话线上花多少钱?

共 同 : 共同:

输入

1 1 1 行: 3 3 3 个用空格隔开的整数: N N N P P P ,以及 K K K
2... P + 1 2...P+1 2...P+1 行: 第 i + 1 i+1 i+1 行为 3 3 3 个用空格隔开的整数: A i A_i Ai B i B_i Bi L i L_i Li

输出

1 1 1 行: 输出 1 1 1 个整数,为 FJ 在这项工程上的最小支出。如果任务不可能完成,输出 − 1 -1 1

样例输入

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

样例输出

4

思路

这道题是一道二分加最短路。

我们就二分答案,长度大于二分值就边权为 1 1 1 ,长度小于等于二分值的就边权为 0 0 0 。我们就跑一边 spfa ,如果最短路的长度小于 k k k ,就可以,否则不可以。(因为多出来的 k k k 条可以免费)

代码

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

struct node {
	int x, to, nxt;
}e[20001];
int n, p, k, KK, le[1001], x, y, z, l, r = 1000000, need[1001], ad, ans = -1;
bool in[1001], yes[1001];
queue<int>q;

void add(int x, int y, int z) {
	e[++KK] = (node){z, y, le[x]}; le[x] = KK;
	e[++KK] = (node){z, x, le[y]}; le[y] = KK;
}

bool work(int spend) {//最短路
	q.push(1);
	while (!q.empty()) {
		int now = q.front();
		q.pop();
		
		for (int i = le[now]; i; i = e[i].nxt) {
			ad = 0;
			if (e[i].x > spend) ad = 1;//这个付不起,距离为1
			if (need[now] + ad < need[e[i].to]) {
				need[e[i].to] = need[now] + ad;
				if (!in[e[i].to]) {
					in[e[i].to] = 1;
					q.push(e[i].to);
				}
			}
		}
		
		in[now] = 0;
	}
	
	if (need[n] > k) return 0;
	return 1;
}

int main() {
	scanf("%d %d %d", &n, &p, &k);//读入
	for (int i = 1; i <= p; i++) {
		scanf("%d %d %d", &x, &y, &z);
		add(x, y, z);//建图
	}
	
	while (l <= r) {//二分
		memset(need, 0x7f, sizeof(need));//初始化
		need[1] = 0;
		in[1] = 1;
		
		int mid = (l + r) >> 1;
		if (work(mid)) {
			r = mid - 1;
			ans = mid;
		}
		else l = mid + 1;
	}
	
	printf("%d", ans);//输出
	
	return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值