【算法】通信线路(二分,堆优化版dijkstra)

news/2024/7/15 17:13:20 标签: 算法, 二分, dijkstra, 图论

题目

        在郊区有 N 座通信基站,P 条 双向 电缆,第 i 条电缆连接基站 Ai 和 Bi。

        特别地,1 号基站是通信公司的总站N 号基站位于一座农场中

        现在,农场主希望对通信线路进行升级,其中升级第 i 条电缆需要花费 Li。

        电话公司正在举行优惠活动。

        农产主可以指定一条从 1 号基站到 N 号基站的路径,并指定路径上不超过 K 条电缆,由电话公司免费提供升级服务。

        农场主只需要支付在该路径上剩余的电缆中,升级价格最贵的那条电缆的花费即可。

        求至少用多少钱可以完成升级。

输入格式

        第 1 行:三个整数 N,P,K。

        第 2..P+1 行:第 i+1 行包含三个整数 Ai,Bi,Li。

输出格式

        包含一个整数表示最少花费。

        若 1 号基站与 N 号基站之间不存在路径,则输出 −1。

数据范围

0 ≤ K < N ≤ 1000
1 ≤ P ≤ 10000
1 ≤ Li ≤ 1000000

思路

我们可以根据以下样例得到一张图

样例:
5 7 1
1 2 5
3 1 4
2 4 8
3 2 3
5 2 9
3 4 7
4 5 6

 

暴力写法,我们可以从0遍历到1000001,找到一个值x:

        1、在选择 1 ~  n 的路线中,比这个值x大的边权为 k 个。

        2、在满足1条件的 x 集合中,选取最小的那个值。

在寻找最短路的时候,可以将大于 x 的边权当作 1 ,把小于等于 x 的边权当作 0 。

dist数组中储存到当前点经过的大于x的边的个数。

从0~1000001时间复杂度太大,可以使用二分进行优化。

 

代码 

#include<bits/stdc++.h>
using namespace std;

const int N = 1010,M = 20010;
typedef pair<int,int> PII;
int n,m,k;// n点数,m边数,k免费电缆数
int h[N],e[M],w[M],ne[M],idx;// 加权邻接表五件套
int dist[N];// 到达第i的点,最少经过多少个超过bound的电缆
bool st[N];// 第i个点的最小值是否已经被确定

void add(int a,int b,int c)
{
    e[idx] = b,w[idx] = c,ne[idx] = h[a],h[a] = idx ++;
}

bool check(int bound)// 堆优化版dijkstra算法
{
    memset(st,0,sizeof(st));// 初始状态,所有点都没有确定最小值
    memset(dist,0x3f,sizeof(dist));// 所有点的距离初始为无穷大
    dist[1] = 0;// 通信公司的总站为0
    priority_queue<PII,vector<PII>,greater<PII>> q;
    q.emplace(0,1);
    st[1] = true;
    while(!q.empty())
    {
        auto t = q.top();// 取出队头节点,此时该点已经确定为最小值
        q.pop();
        int x = t.second;
        st[x] = false;
        for(int i = h[x]; i != -1; i = ne[i])
        {
            int j = e[i],v = w[i] > bound;// 如果这条边的边权大于bound,则边权为1
            if(dist[j] > dist[x] + v)
            {
                dist[j] = dist[x] + v;
                if(!st[j])
                {
                    st[j] = true;
                    q.emplace(dist[j],j);
                }
            }
        }
    }
    return dist[n] <= k;
}


int main()
{
    cin >> n >> m >> k;// n点数,m边数,k免费电缆数

    memset(h,-1,sizeof(h));// 将表头初始化为-1
    while(m --)// 输入m条边
    {
        int a,b,c;
        cin >> a >> b >> c;
        add(a,b,c),add(b,a,c);// 建立有权值的无向图
    }
    int l = 0,r = 1e6 + 1;
    while(l < r)
    {
        int mid = (l + r) / 2;
        if(check(mid)) r = mid;
        else l = mid + 1;
    }
    if(l == 1e6 + 1) l = -1;
    cout << l << endl;
    return 0;
}


http://www.niftyadmin.cn/n/5157260.html

相关文章

密钥管理系统功能及作用简介 安当加密

密钥管理系统的功能主要包括密钥生成、密钥注入、密钥备份、密钥恢复、密钥更新、密钥导出和服务&#xff0c;以及密钥的销毁等。 密钥生成&#xff1a;通过输入一到多组的密钥种子&#xff0c;按照可再现或不可再现的模式生成所需要的密钥。一般采用不可再现模式作为密钥生成…

React中动态添加和删除元素

在React中&#xff0c;可以通过状态&#xff08;state&#xff09;和事件处理器&#xff08;event handlers&#xff09;来动态添加和删除元素。 首先&#xff0c;需要使用状态&#xff08;state&#xff09;来存储要动态添加或删除的元素。可以使用useState钩子来创建一个状态…

Cubase 13 官宣升级,用户界面重新设计,音乐创作“更自然、更直观、更方便”,全面支持 MIDI 2.0

Cubase 13简介 Steinberg发布Cubase 13升级&#xff0c;带有显著的重新设计了用户界面&#xff0c;还有众多新功能和提升作曲、制作、混音和给你创意的工作流。 获取地址 Steinberg Cubase Pro 13 功能新特性 随时随地的混音&#xff1a; MixConsole重新设计了更简洁的界面…

ES6模块介绍—module的语法import、export简单介绍及用法

ES6模块语法 模块功能主要由两个命令构成&#xff1a;export和import。export命令用于规定模块的对外接口&#xff0c;import命令用于输入其他模块提供的功能。 一个模块就是一个独立的文件。该文件内部的所有变量&#xff0c;外部无法获取。如果你希望外部能够读取模块内部的…

德国爆发大规模勒索软件攻击,超70个城市市政服务瘫痪

根据11月3日消息称&#xff0c;德国西部本周发生大规模勒索软件攻击&#xff0c;多个城市和地区的地方政府服务陷入瘫痪。 上周一&#xff08;10月30日&#xff09;早上&#xff0c;德国地方市政服务提供商Sdwestfalen IT公司的服务器被未知的黑客团伙加密。为阻止恶意软件传播…

JavaScript作用域实战

● 首先&#xff0c;我们先创建一个函数&#xff0c;和以前一样&#xff0c;计算一个年龄的 function calcAge(birthYear) {const age 2037 - birthYear;return age; }● 然后我们创建一个全局变量&#xff0c;并调用这个函数 const firstName "IT知识一享"; cal…

配置jar包开机自启动,会在启动之后自动停止

通过systemctl服务启动 该方式将java应用的启动脚本托管给systemctl服务&#xff0c;通过systemctl的一系列命令配置应用的开机启动。 1&#xff09;进入到系统的/usr/lib/systemd/system目录下 cd /etc/systemd/system2&#xff09;添加.service文件 vim test.service [Uni…

RxJava/RxAndroid的基本使用方法(一)

文章目录 一、什么是RxJava二、使用前的准备1、导入相关依赖2、字段含意3、Upstream/Downstream——上/下游4、BackPressure5、BackPressure策略6、“热” and “冷” Observables7、 基类8、事件调度器9、操作符是什么&#xff1f; 三、RxJava的简单用法1、Observable——Obse…