BZOJ 1614: [Usaco2007 Jan]Telephone Lines架设电话线 (二分+spfa)

1614: [Usaco2007 Jan]Telephone Lines架设电话线

Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 1325  Solved: 570 [Submit][Status][Discuss]

Description

Farmer John打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务。于是,FJ必须为此向电信公司支付一定的费用。 FJ的农场周围分布着N(1 <= N <= 1,000)根按1..N顺次编号的废弃的电话线杆,任意两根电话线杆间都没有电话线相连。一共P(1 <= P <= 10,000)对电话线杆间可以拉电话线,其余的那些由于隔得太远而无法被连接。 第i对电话线杆的两个端点分别为A_i、B_i,它们间的距离为 L_i (1 <= L_i <= 1,000,000)。数据中保证每对{A_i,B_i}最多只出现1次。编号为1的电话线杆已经接入了全国的电话网络,整个农场的电话线全都连到了编号为N的电话线杆上。也就是说,FJ的任务仅仅是找一条将1号和N号电话线杆连起来的路径,其余的电话线杆并不一定要连入电话网络。 经过谈判,电信公司最终同意免费为FJ连结K(0 <= K < N)对由FJ指定的电话线杆。对于此外的那些电话线,FJ需要为它们付的费用,等于其中最长的电话线的长度(每根电话线仅连结一对电话线杆)。如果需要连结的电话线杆不超过 K对,那么FJ的总支出为0。 请你计算一下,FJ最少需要在电话线上花多少钱。

Input

  • 第1行: 3个用空格隔开的整数:N,P,以及K

  • 第2..P+1行: 第i+1行为3个用空格隔开的整数:A_i,B_i,L_i

Output

  • 第1行: 输出1个整数,为FJ在这项工程上的最小支出。如果任务不可能完成, 输出-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

输入说明:

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

Sample Output

4

输出说明:

FJ选择如下的连结方案:1->3;3->2;2->5,这3对电话线杆间需要的 电话线的长度分别为4、3、9。FJ让电信公司提供那条长度为9的电话线,于是, 他所需要购买的电话线的最大长度为4。

HINT

思路:一开始把电话线条数和长度分别作为第一第二关键字,然后spfa.然后记录路径,找k个最大的以后的中最长的电话线就是答案。发现样例就是反例。。智力-2.

正确的做法是二分电话线的最大长度,大于最大长度的电话线交给电信公司取搞,看交给电信公司搞的电话线数目是否小于等于k.

二分的功夫还是不到家呀。。想不到。。 不过这道题和那个中国印度被喜马拉雅山脉阻隔,二分+bfs判断连通性的题目有点类似呢。

  1/* ***********************************************
  2Author :111qqz
  3Created Time :2016年04月02日 星期六 17时50分13秒
  4File Name :code/bzoj/1614.cpp
  5************************************************ */
  6
  7#include <cstdio>
  8#include <cstring>
  9#include <iostream>
 10#include <algorithm>
 11#include <vector>
 12#include <queue>
 13#include <set>
 14#include <map>
 15#include <string>
 16#include <cmath>
 17#include <cstdlib>
 18#include <ctime>
 19#define fst first
 20#define sec second
 21#define lson l,m,rt<<1
 22#define rson m+1,r,rt<<1|1
 23#define ms(a,x) memset(a,x,sizeof(a))
 24typedef long long LL;
 25#define pi pair < int ,int >
 26#define MP make_pair
 27
 28using namespace std;
 29const double eps = 1E-8;
 30const int dx4[4]={1,0,0,-1};
 31const int dy4[4]={0,-1,1,0};
 32const int inf = 0x3f3f3f3f;
 33const int N=1E3+7;
 34int n,m,k;
 35int d[N];
 36bool inq[N];
 37vector < pi >edge[N];
 38
 39void init()
 40{
 41    for ( int i = 0 ; i <= n ; i++) edge[i].clear();
 42
 43}
 44
 45int spfa(int X) //X表示最大花费
 46{
 47    queue<int>q;
 48    ms(inq,false);
 49    ms(d,0x3f);
 50    q.push(1);
 51    inq[1] = true;
 52    d[1] = 0; // d[i]表示从1到i需要电信公司帮忙建的电话线杆的个数。
 53
 54
 55    while (!q.empty())
 56    {
 57	int u = q.front();
 58	q.pop();
 59	inq[u] = false;
 60
 61	int siz = edge[u].size();
 62
 63	for ( int i = 0 ; i < siz ; i++)
 64	{
 65	    int v = edge[u][i].fst;
 66	    int w = edge[u][i].sec>X?1:0;
 67
 68	    if (d[v]>d[u]+w)
 69	    {
 70		d[v] = d[u] + w;
 71		if (inq[v]) continue;
 72		inq[v] = true;
 73		q.push(v);
 74	    }
 75	}
 76    }
 77    return d[n];
 78
 79}
 80
 81void bin()
 82{
 83    int l = 0 ;
 84    int r = 1000000;
 85    int mid;
 86    int ans;
 87
 88    while (l<=r)
 89    {
 90	mid = (l+r)/2;
 91	if (spfa(mid)<=k) ans = mid,r=mid-1;
 92	else l = mid + 1;
 93    }
 94    printf("%d\n",ans);
 95}
 96int main()
 97{
 98	#ifndef  ONLINE_JUDGE 
 99	freopen("code/in.txt","r",stdin);
100  #endif
101
102	init();
103	scanf("%d%d%d",&n,&m,&k);
104	for ( int i = 1 ; i <= m ; i++)
105	{
106	    int u,v,w;
107	    scanf("%d%d%d",&u,&v,&w);
108	    edge[u].push_back(MP(v,w));//以电话线数目为第一关键字,长度为第二关键字。
109	    edge[v].push_back(MP(u,w));
110	}
111	if (spfa(inf)==inf)
112	{
113	    puts("-1");
114	    return 0;
115	}
116	bin();
117
118  #ifndef ONLINE_JUDGE  
119  fclose(stdin);
120  #endif
121    return 0;
122}