电话线
时间限制(普通/Java) : 3000 MS/ 3000 MS 运行内存限制 : 65536 KByte
总提交 : 38 测试通过 : 13 描述
Farmer John打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务。于是,FJ必须为此向电信公司支付一定的费用。 输入
* 第1行: 3个用空格隔开的整数:N,P,以及K 输出
* 第1行: 输出1个整数,为FJ在这项工程上的最小支出。如果任务不可能完成,输出-1 样例输入 5 7 1 样例输出 4 提示
输入说明: 题目来源 ZXY |
题目地址: http://218.194.91.48/acmhome/problemdetail.do?&method=showdetail&id=1066
方法: 二分枚举+搜索。
非常好的题目。。。
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
struct point{
int len,to,next;
}p[20100];
int f[1100];
int dis[11000];
int mark[1100];
int n,k,pp,cnt;
int que[400000];
int bfs(int mx){
int s,t,v;
int now,nx,num;
que[s=t=0]=1;
memset(mark,-1,sizeof(mark));
mark[1]=0;
while(s<=t){
now=que[s++];
for(v=f[now];v!=-1;v=p[v].next){
num=mark[now];
nx=p[v].to;
if(p[v].len>mx) num++;
if(num>k) continue;
if(mark[nx]!=-1)
if(mark[nx]<=num)
continue;
if(nx==n) return 1;
mark[nx]=num;
que[++t]=nx;
}
}
return 0;
}
int deal(){
int l=0,r=pp,mid;
if(bfs(dis[r])==0) return -1;
while(l<=r){
if(l==r) break;
mid=(l+r)>>1;
if(bfs(dis[mid])==1)
r=mid;
else
l=mid+1;
}
return dis[l];
}
int main(){
int i,j;
int x,y,len;
while(~scanf("%d%d%d",&n,&pp,&k)){
memset(f,-1,sizeof(f));
dis[0]=0;
for(i=1,cnt=0;i<=pp;i++){
scanf("%d%d%d",&x,&y,&len);
p[cnt].to=y;
p[cnt].len=len;
p[cnt].next=f[x];
f[x]=cnt++;
p[cnt].to=x;
p[cnt].len=len;
p[cnt].next=f[y];
f[y]=cnt++;
dis[i]=len;
}
sort(dis,dis+pp+1);
printf("%d\n",deal());
}
return 0;
}