架設電話線 \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
樣例輸出
思路
這道題是一道二分加最短路。
我們就二分答案,長度大于二分值就邊權為 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;
}