• 电话网络


    电话网络

    问题描述

      由于地震使得连接汶川县城电话线全部损坏,假如你是负责将电话线接到震中汶川县城的负责人,汶川县城周围分布着N(1≤N≤1,000)根按 1..N 顺次编号的废弃的电话线杆,任意两根电话线杆间都没有电话线相连。一共P(1≤P≤10,000)对电话线杆间可以拉电话线,其余的由于地震使得无法被连接。
      第i对电话线杆的两个端点分别为Ai,Bi,它们间的距离为Li(1≤Li≤1,000,000)。数据中保证每对(Ai,Bi)最多只出现1次。编号为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

    题解

    为了花费最少,免费的电话线杆要尽可能多,当K对电话线杆都用完之后,最长的电话线越短越好

    即,求一条从1到n的路径,使得这条路径上第K+1长的路最短

    考虑二分总花费mid,即需要付钱的最长的电话线,那么所有长度大于mid的电话线都视为免费,用最短路求从1到n需要的最少的免费的电话线数,若大于K,说明当前二分的mid过小,反之,则当前mid满足条件且可能更大

     1 #include <cstring>
     2 #include <cstdio>
     3 const int maxn=1005;
     4 int n,m,K,fir[1005],num,dis[1005],q[1005];
     5 bool vis[1005];
     6 struct node{
     7     int u,w,nex;
     8 }g[20005];
     9 void add(int x,int y,int z)
    10 {
    11     g[++num].u=y;       g[num].w=z;
    12     g[num].nex=fir[x];  fir[x]=num;
    13 }
    14 void spfa(int mid)
    15 {
    16     int u,v,k,h,t;
    17     memset(dis,63,sizeof(dis));
    18    // printf("%d
    ",dis[0]);
    19     memset(vis,0,sizeof(vis));
    20     dis[1]=0;
    21     h=0;  t=1;  q[1]=1;  vis[1]=1;
    22     while (h!=t)
    23     {
    24         (++h)%=maxn;
    25         u=q[h];  vis[u]=0;
    26         for (k=fir[u];k;k=g[k].nex)
    27         {
    28             v=g[k].u;
    29             if (dis[v]>dis[u]+(g[k].w>mid))
    30             {
    31                 dis[v]=dis[u]+(g[k].w>mid);
    32                 if (!vis[v])
    33                 {
    34                     vis[v]=1;
    35                     if (dis[v]<dis[q[(h+1)%maxn]])
    36                       q[h]=v,h=(h-1+maxn)%maxn;
    37                     else (++t)%=maxn,q[t]=v;
    38                 }
    39             }
    40         }
    41     }
    42     return;
    43 }
    44 int main()
    45 {
    46     int i,j,x,y,z;
    47     scanf("%d%d%d",&n,&m,&K);
    48     for (i=1;i<=m;i++)
    49       scanf("%d%d%d",&x,&y,&z),
    50       add(x,y,z),add(y,x,z);
    51     int l=0,r=1e6,mid,ans=-1;
    52     while (l<=r)
    53     {
    54         mid=(l+r)>>1;
    55         spfa(mid);
    56         if (dis[n]<=K) ans=mid,r=mid-1;
    57         else l=mid+1;
    58     }
    59     printf("%d",ans);
    60     return 0;
    61 }
  • 相关阅读:
    kmp算法详解
    艾伦.席森.图灵
    gcd详解
    Shortest Prefixes 字典树模板
    Hat's Words 字典树变式
    统计难题 字典树模板
    Phone List 字典树模板
    字典树详解
    Basic Gcd Problem 线性筛
    codeforces 454 D. Little Pony and Harmony Chest(状压dp)
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/15085293.html
Copyright © 2020-2023  润新知