Telephone Lines [POJ3662] [二分答案]
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] [二分答案]