电话网络(phone)

 电话网络(phone)

输入文件:phone.in

输出文件:phone.out

【题目描述】

绿化工程终于完成,整个园区生机勃勃。但是,很不幸的是,在绿化过程中,工人们和进出的车辆将铺设好的电话线全部破坏了。Neyc的领导很生气,问题很严重。为了保住面子,工程队负责人,希望尽快恢复园区的电信,他把这个任务交给了你。

已知,园区周围分布N(1<=n<=1000)根按1…n排列的电话线杆,电话线杆之间可以拉电话线。第i对电话线杆的两个端点分别为Ai,Ri,它们间的距离为Li(1<=li<=1000000)。数据中保证每对最多只出现一次。编号为1的电话线杆已经接入了全国的电话网络,整个园区的电话线全部连到了编号为N的电话线杆上。也就是说,你的任务仅仅是找一条将1号和N号电话线杆连起来的路径,其余的电话线杆并不一定要连入电话网络。

绿化工程的负责人与电信公司协商后,电信公司决定免费为园区连接K(0<=k<n)对由你指定的电话线杆。对于此外的那些电话线,就必需为它们付费,总费用等于其中最长的电话线长度(每根电话线仅连接一对电话线杆),其它长度不付费。如果需要连接的电话线杆不超过K对,那么总支出为0。

现在,你就要设计一个费用最少的方案。最后,计算出将电话线引到园区最少需要花多少钱?

【输入格式】

  输入文件的第一行包含三个用空格隔开的整数:N ,P和K。

  第二行到第P+1行:每行分别都为三个用空格隔开的整数:Ai Bi和Li。

【输出格式】

  输出文件仅包含一个整数,表示在这项工程上的最小支出。如果任务不可能完成,则输出-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

【样例输出】

    4

=======================

二分加最短路

可以二分出一个答案,构建最短路模型,若cost>mid则之间的花费就是1.

若dis[n]>k返回false,否则返回true 

----------------------------------------------

最开始用的是二分加搜索,就爆了5个点

function check(t_,times:longint):boolean;
var
  p:node;
  flag:boolean;
begin
  check:=false;
  if t_=n then exit(true);
  p:=t[t_];
  while p<>nil do
    begin
      if (p^.cost<=mid)and(f[p^.x]) then
        begin
          f[p^.x]:=false;
          flag:=check(p^.x,times);
          if flag then exit(true);
          f[p^.x]:=true;
        end;
      if (p^.cost>mid) and (times>0) and f[p^.x] then
        begin
          f[p^.x]:=false;
          flag:=check(p^.x,times-1);
          if flag then exit(true);
          f[p^.x]:=true;
        end;
      p:=p^.next;
    end;
end;
        

=======================

type
  node=^re;
  re=record
       x,cost:longint;
       next:node;
     end;
     
var
  n,p,k:longint;
  t:array[1..1000]of node;
  f,v:array[1..1000]of boolean;
  dis:array[1..1000]of longint;
  h:array[1..100000]of longint;
  l,r,mid,ans:longint;
  
procedure init;
begin
  assign(input,'phone.in');
  assign(output,'phone.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

procedure insert(a,b,c:longint);
var
  p:node;
begin
  new(p);
  p^.x:=b;
  p^.cost:=c;
  p^.next:=t[a];
  t[a]:=p;
end;

function spfa:boolean;
var
  p:node;
  l,r:longint;
begin
  v[1]:=true;  dis[1]:=0;
  l:=0; r:=1;
  h[1]:=1;
  repeat
    inc(l);
    p:=t[h[l]];
    v[h[l]]:=false;
    while p<>nil do
      begin
        if p^.cost<=mid then
          begin
            if dis[h[l]]<dis[p^.x] then
              begin
                dis[p^.x]:=dis[h[l]];
                if not v[p^.x] then
                  begin
                    v[p^.x]:=true;
                    inc(r);
                    h[r]:=p^.x;
                  end;
              end;
          end;
        if p^.cost>mid then
          begin
            if dis[h[l]]+1<dis[p^.x] then
              begin
                dis[p^.x]:=dis[h[l]]+1;
                if not v[p^.x] then
                  begin
                    v[p^.x]:=true;
                    inc(r);
                    h[r]:=p^.x;
                  end;
              end;
          end;
        p:=p^.next;
      end;
  until l>r;
  if dis[n]-k>0 then exit(false)
                else exit(true);
end;

procedure main;
var
  i:longint;
  a,b,c,tot:longint;
begin
  readln(n,p,k);
  for i:=1 to n do
    t[i]:=nil;
  tot:=0;
  for i:=1 to p do
    begin
      readln(a,b,c);
      if tot<c then tot:=c;
      insert(a,b,c);
      insert(b,a,c);
    end;
  l:=0; r:=tot;
  ans:=-1;
  while l<=r do
    begin
      fillchar(f,sizeof(f),true);
      mid:=(l+r)shr 1;
      fillchar(v,sizeof(v),false);
      fillchar(dis,sizeof(dis),$7);
      if spfa then begin ans:=mid; r:=mid-1; end
              else l:=mid+1;
      //f[1]:=false;
      //times:=k;
      //if check(1,k) then begin ans:=mid; r:=mid-1; end
                    //else l:=mid+1;

    end;
  writeln(ans);
end;

begin
  init;
  main;
  terminate;
end.  


 

                
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值