题解 | TelephoneLines-牛客假日团队赛8F题

F-Telephone Lines_牛客假日团队赛8

https://ac.nowcoder.com/acm/contest/1069/F

题目描述

Farmer John wants to set up a telephone line at his farm. Unfortunately, the phone company is uncooperative, so he needs to pay for some of the cables required to connect his farm to the phone system.
There are forlorn telephone poles conveniently numbered 1..N that are scattered around Farmer John's property; no cables connect any them. A total of pairs of poles can be connected by a cable; the rest are too far apart.
The i-th cable can connect the two distinct poles Ai and Bi, with length units if used. The input data set never names any pair more than once. Pole 1 is already connected to the phone system, and pole N is at the farm. Poles 1 and N need to be connected by a path of cables; the rest of the poles might be used or might not be used.
As it turns out, the phone company is willing to provide Farmer John with lengths of cable for free. Beyond that he will have to pay a price equal to the length of the longest remaining cable he requires (each pair of poles is connected with a separate cable), or 0 if he does not need any additional cables.
Determine the minimum amount that Farmer John must pay.

输入描述:

* Line 1: Three space-separated integers: N, P, and K
* Lines 2..P+1: Line i+1 contains the three space-separated integers: , and

输出描述:

* Line 1: A single integer, the minimum amount Farmer John can pay. If it is impossible to connect the farm to the phone company, print -1.

示例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
说明
There are 5 poles. Pole 1 cannot be connected directly to poles 4 or 5. Pole 5 cannot be connected directly to poles 1 or 3. All other pairs can be connected. The phone company will provide one free cable.
If pole 1 is connected to pole 3, pole 3 to pole 2, and pole 2 to pole 5 then Farmer John requires cables of length 4, 3, and 9. The phone company will provide the cable of length 9, so the longest cable needed has length 4.

解答

Tips:看到这样的字眼,你就要想起二分

最大……里的最小……

or

最小……里的最大……

那么这题显然是一个最短路问题,区别于别的最短路,本题可以有 KK 条免费线路

第一个想到的当然是枚举~(≧▽≦)/~啦啦啦
然后就 TLETLE 了QAQ
这道题目显然要用二分去做,那么,二分什么呢?当然是二分答案,本题有一个很和谐的友好的字眼:答案是长的长度。
至于思路如下:首先二分答案,将所有线中大于答案的标记为 11 (需要使用一次免费机会),不大于答案的标记为0(不需要使用免费机会),有人说,这题不能用Dijkstra?当然不行,为什么呢?因为迪杰斯特拉算法效率低下他无法对0边权进行处理,极有可能死循环,而SPFA的原理是:更新后不低于当前长度就不进队列,可以有效的处理0的问题。
代码如下
#include<bits/stdc++.h>//万能头
using namespace std;
inline int read() {//快读
    int X=0,w=0;
    char ch=0;
    while(!isdigit(ch)) {
        w|=ch=='-';
        ch=getchar();
    }
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
inline double dbread() {//小数快读
    double X=0,Y=1.0;
    int w=0;
    char ch=0;
    while(!isdigit(ch)) {
        w|=ch=='-';
        ch=getchar();
    }
    while(isdigit(ch)) X=X*10+(ch^48),ch=getchar();
    ch=getchar();
    while(isdigit(ch)) X+=(Y/=10)*(ch^48),ch=getchar();
    return w?-X:X;
}
inline void write(int x) {//快些
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}

至此为止,上面都是我的模板AwA

struct node {//程序核心
    int to,next,val;
} e[20005];//前向星
int tot=0,head[1005],dis[1005],n,k,p,ans=-1;
bool vis[1005];
queue<int> q;//SPFA队列
void add(int u,int v,int w) {//建边(前向星)
    e[++tot]=(node) {
        v,head[u],w
    };
    head[u]=tot;
}
bool spfa(int x) {//SPFA(judge函数)
    memset(dis,42,sizeof(dis));//初始化,因为有多次judge
    memset(vis,0,sizeof(vis));//初始化,因为有多次judge
    dis[1]=0;
    q.push(1);
    vis[1]=true;
    int s;
    while(!q.empty()) {//SPFA(STL队列实现)
        int now=q.front();
        q.pop();
        for(int i=head[now]; i; i=e[i].next) {
            if(e[i].val>x)s=dis[now]+1;//如果大于当前二分出来的答案(如上所述)
            else s=dis[now];
            if(s<dis[e[i].to]) {
                dis[e[i].to]=s;
                if(!vis[e[i].to])q.push(e[i].to),vis[e[i].to]=true;
            }
        }
        vis[now]=0;
    }
    if(dis[n]<=k)return 1;//如果需要免费的边在范围之内,说明这种答案是可行的,寻找更小的答案
    return 0;
}
int main() {
    n=read();//读入
    p=read();//读入
    k=read();//还是读入
    for(int i=1; i<=p; i++) {//建边
        int u,v,w;
        u=read();
        v=read();
        w=read();
        add(u,v,w);//因为是无向图,所以要建来去两边
        add(v,u,w);
    }
    int l=0,r=1000000;
    //二分,我这里直接从最大距离开始查找,你们也可以从输入的数据中找最大值(可能会比我这个快一点)
    while(l<=r) {//二分
        int mid=(l+r)>>1;
        if(spfa(mid)) {
            ans=mid;//保存下当前答案,就可以放心的去找更小的了
            r=mid-1;
        } else l=mid+1;
    }
    write(ans);//输出
    return 0;//这可是个好习惯
}
关于二分,有很多写法,我个人喜欢这种写法,找到答案之后保存下来,有一些写法是输出R或L的,这个就要看个人喜好了

来源:蒟蒻小水楼
全部评论

相关推荐

不愿透露姓名的神秘牛友
07-15 17:17
听说过付费实习,没想到这么贵啊我去,要不我给你个腰子吧
哈哈哈,你是老六:这种公司一定要注意啊,不要随便签合同,只要签了后面钱可能回不来,而且你通过法律途径也弄不回
点赞 评论 收藏
分享
零OFFER战士:另一个版本查看图片
点赞 评论 收藏
分享
06-10 21:15
门头沟学院 Java
宁阿:好多这种没🧠的公司,他们估计都不知道毕业的人不能给安排实习岗
实习吐槽大会
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务