题解|《算法竞赛进阶指南》Telephone Lines

B-Telephone Lines_0x61 图论-最短路

https://ac.nowcoder.com/acm/contest/1055/B

题面描述:

在某地有n座通信基站,p条双向电缆,第i条连接ai和bi。其中1号基站是总站,现有人希望通讯公司可以对电缆进行升级以期更好地使用,其中对第i条升级需要支付wi。

而电缆公司正在搞活动,某人可以指定一条从1号基站到n号基站的路径,并指定路径上不超过k条电缆,通讯公司可免费进行升级,而收取的费用也仅仅为升级该路径上剩下电缆中最贵的所需花费即可。

问至少要多少钱能完成升级?

简单来说,就是求一条从1到n的最短路,使得路径上第k+1大的边权最小


思路:

我们可以通过二分查找出第k+1条边的边权,边界值l为0,r为1000000.
至于内部如何处理,我们可以将边权小于mid的边的边权看做为0,大于的看做为1,然后跑一边最短路,跑出n点的最短路长度,如果大于k,说明mid小了,所以l=mid+1; ,如果小于k,说明mid大了,所以r=mid;


我用的最短路算法为优先队列优化的dij,再加上O(logn)的二分查找,总的时间复杂度为

my code

#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int MAXN = 1000010;
const int MAXM = 2000010;

struct node{
    int w,now;
    inline bool operator < (node x)const{
        return w>x.w;
    }
};

int n,m,k;
priority_queue <node> q;

struct Edge{
    int u,v,w,nxt;
}e[MAXM<<1];

int head[MAXN],vis[MAXN],cnt,e_w[MAXM<<1],dist[MAXN];

void add_edge(int u,int v,int w){
    e[++cnt].v=v;
    e[cnt].w=w;
    e[cnt].nxt=head[u];
    head[u]=cnt;
}

void dij(){
    memset(dist,0x3f,sizeof(dist));
    q.push((node){0,1}); dist[1] = 0;
    while(!q.empty()){
        node x=q.top();
        q.pop();
        int u=x.now;
        if(dist[u]<x.w)continue;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v,w=e_w[i];
            if(dist[v]>dist[u]+w){
                dist[v]=dist[u]+w;
                q.push((node){dist[v],v});
            }
        }
    }
}

void change(int len){
    for(int i=1;i<=cnt;i++){
        if(e[i].w<=len)e_w[i]=0;
        else e_w[i]=1;
    }
    dij();
}

bool can_use(){
    if(dist[n]>k)return 0;
    else return 1;
}

signed main(){
     cin >> n >> m >> k;
    for(int i=1;i<=m;i++){
        int u,v,w;
           cin >> u >> v >> w;
        add_edge(u,v,w);
        add_edge(v,u,w);
    }
    int l=0,r=(int)1e9;
    while(l<r){
        int mid=(l+r)>>1;
        change(mid);
        if(can_use()){
            r=mid;
        }
        else{
            l=mid+1;
        }
    }
    if(l==1e9)cout<<-1<<endl;
    else cout<<l<<endl;
    return 0;
}
全部评论
前排
点赞 回复 分享
发布于 2019-08-21 08:27

相关推荐

真tmd的恶心,1.面试开始先说我讲简历讲得不好,要怎样讲怎样讲,先讲背景,再讲技术,然后再讲提升多少多少,一顿说教。2.接着讲项目,我先把背景讲完,开始讲重点,面试官立即打断说讲一下重点,无语。3.接着聊到了项目的对比学习的正样本采样,说我正样本采样是错的,我解释了十几分钟,还是说我错的,我在上一家实习用这个方法能work,并经过市场的检验,并且是顶会论文的复现,再怎么不对也不可能是错的。4.面试官,说都没说面试结束就退出会议,把面试者晾在会议里面,丝毫不尊重面试者难受的点:1.一开始是讲得不好是欣然接受的,毕竟是学习。2.我按照面试官的要求,先讲背景,再讲技术。当我讲完背景再讲技术的时候(甚至已经开始蹦出了几个技术名词),凭什么打断我说讲重点,是不能听出人家重点开始了?这也能理解,每个人都有犯错,我也没放心上。3.我自己做过的项目,我了解得肯定比他多,他这样贬低我做过的项目,说我的工作是错误的,作为一个技术人员,我是完全不能接受的,因此我就和他解释,但无论怎么解释都说我错。凭什么,作为面试官自己不了解相关技术,别人用这个方式work,凭什么还认为这个方法是错的,不接受面试者的解释。4.这个无可厚非,作为面试官,不打招呼就退出会议,把面试者晾着,本身就是有问题。综上所述,我现在不觉得第一第二点也是我的问题,面试官有很大的问题,就是专门恶心人的,总结面试官说教,不尊重面试者,打击面试者,不接受好的面试者,技术一般的守旧固执分子。有这种人部门有这种人怎么发展啊。最后去查了一下,岗位关闭了。也有可能是招到人了来恶心人的,但是也很cs
牛客20646354...:招黑奴啊,算法工程师一天200?
点赞 评论 收藏
分享
09-22 23:17
门头沟学院 Java
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

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