架设电话线 \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\} {Ai,Bi} 最多只出现 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
1∼4 :
N
<
=
10
,
P
<
=
20
;
N<=10,P<=20;
N<=10,P<=20;
数据点
5
∼
6
5\sim 6
5∼6 :
N
<
=
50
,
P
<
=
200
;
N<=50,P<=200;
N<=50,P<=200;
数据点
7
∼
9
7\sim 9
7∼9 :
N
<
=
1000
,
P
<
=
1000
;
N<=1000,P<=1000;
N<=1000,P<=1000;
数据点
10
∼
11
10\sim 11
10∼11 :
N
<
=
1000
,
P
<
=
5000
;
N<=1000,P<=5000;
N<=1000,P<=5000;
数据点
12
∼
13
12\sim 13
12∼13 :
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 1……n 顺序编号的废弃的电话线杆,任意两根线杆之间没有电话线连接,一共有 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;
}