1. 程式人生 > >Telephone Lines [POJ3662] [二分答案]

Telephone Lines [POJ3662] [二分答案]

空格 技術 分享圖片 show span return 電話 cli 沒有

Description

Farmer John打算將電話線引到自己的農場,但電信公司並不打算為他提供免費服務。於是,FJ必須為此向電信公司支付一定的費用。 FJ的農場周圍分布著N(1 <= N <= 1,000)根按1..N順次編號的廢棄的電話線桿,任意兩根電話線桿間都沒有電話線相連。一共P(1 <= P <= 10,000)對電話線桿間可以拉電話線,其余的那些由於隔得太遠而無法被連接。
第i對電話線桿的兩個端點分別為A_i、B_i,它們間的距離為Li (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

Sample Output

4

Hint

輸入說明:
一共有5根廢棄的電話線桿。電話線桿1不能直接與電話線桿4、5相連。電話線桿5不能直接與電話線桿1、3相連。其余所有電話線桿間均可拉電話線。電信公司可以免費為FJ連結一對電話線桿。
輸出說明:
FJ選擇如下的連結方案:1->3;3->2;2->5,這3對電話線桿間需要的電話線的長度分別為4、3、9。FJ讓電信公司提供那條長度為9的電話線,於是,他所需要購買的電話線的最大長度為4。

Analysis

我們二分一個k+1的大小lim,統計最少需要用到大於lim的路的條數,在k以內就夠

如何統計最少需要用多少條大於lim的路?

把每一條大於lim的路權值看作1,跑最短路即可。

Code

技術分享圖片
 1 #include<set>
 2 #include<map>
 3 #include<queue>
 4 #include<stack>
 5 #include<cmath>
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<iostream>
 9 #include<algorithm>
10 #define RG register int
11 #define rep(i,a,b)    for(RG i=a;i<=b;++i)
12 #define per(i,a,b)    for(RG i=a;i>=b;--i)
13 #define ll long long
14 #define inf (1<<29)
15 #define maxn 1005
16 #define maxm 10005
17 #define add(x,y,z) e[++cnt]=(E){y,head[x],z},head[x]=cnt
18 using namespace std;
19 int n,m,k,cnt;
20 int dis[maxn],vis[maxn],head[maxn];
21 struct E{
22     int v,next,val;
23 }e[maxm<<1];
24 inline int read()
25 {
26     int x=0,f=1;char c=getchar();
27     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
28     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
29     return x*f;
30 }
31 
32 int check(int lim)
33 {
34     queue<int> que;que.push(1);
35     memset(dis,63,sizeof(dis));dis[1]=0;
36     RG u,v,d;
37     while(!que.empty())
38     {
39         u=que.front(),que.pop(),vis[u]=0;
40         for(RG i=head[u];i;i=e[i].next)
41         {
42             v=e[i].v,d=e[i].val>lim?1:0;
43             if(dis[v]>dis[u]+d)
44             {
45                 dis[v]=dis[u]+d;
46                 if(!vis[v])    vis[v]=1,que.push(v);
47             }
48         }
49     }
50     return dis[n]<=k;
51 }
52 
53 int main()
54 {
55     n=read(),m=read(),k=read();
56     for(RG i=1,a,b,c;i<=m;i++)
57     {
58         a=read(),b=read(),c=read();
59         add(a,b,c),add(b,a,c);
60     }
61     int l=0,r=1000005,ans=-1,mid;
62     while(l<=r)
63     {
64         mid=l+r>>1;
65         if(check(mid))    ans=mid,r=mid-1;
66         else            l=mid+1;
67     }
68     cout<<ans;
69     return 0;
70 }
View Code

Telephone Lines [POJ3662] [二分答案]