单源最短路的综合应用

1135. 新年好 - AcWing题库

单源最短路和暴搜的结合 

import java.util.*;

class PII implements Comparable<PII>{
    int num, distance;
    
    public PII(int num, int distance){
        this.num = num;
        this.distance = distance;
    }
    
    public int compareTo(PII o){
        return distance - o.distance;
    }
}

public class Main{
    static int N = 50010, M = 100010 * 2, idx, n, m, INF = 0x3f3f3f3f;
    static int[] h = new int[N], e = new int[M], ne = new int[M], w = new int[M];
    static boolean[] st = new boolean[N];
    static int[][] dist = new int[6][N];
    static int[] source = new int[6];
    
    //邻接表存储
    public static void add(int a, int b, int c){
        e[idx] = b;
        w[idx] = c;
        ne[idx] = h[a];
        h[a] = idx ++;
    }
    
    //打表,预处理
    public static void dijkstra(int u, int[] dist){
        PriorityQueue<PII> q = new PriorityQueue<>();
        Arrays.fill(st, false);
        Arrays.fill(dist, INF);
        
        q.offer(new PII(u, 0));
        dist[u] = 0;
        
        while(!q.isEmpty()){
            PII t = q.poll();
            int distance = t.distance;
            int num = t.num;
            
            if(st[num]) continue;//遍历过
            st[num] = true;//进行标记
            
            for(int i = h[num]; i != -1; i = ne[i]){
                int j = e[i];
                if(dist[j] > distance + w[i]){
                    dist[j] = distance + w[i];
                    q.offer(new PII(j, dist[j]));
                }
            }
        }
    }
    
    public static int dfs(int u, int start, int distance){
        if(u == 6) return distance;
        
        int res = INF;
        //枚举五个亲戚
        for(int i = 1; i <= 5; i ++){
            if(!st[i]){
                int next = source[i];//取出亲戚的编号
                st[i] = true;//标记为已用过
                res = Math.min(res, dfs(u + 1, i, distance + dist[start][next]));//从表中查询
                st[i] = false;//恢复现场
            }
        }
        return res;
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        
        Arrays.fill(h, -1);//初始化表头
        
        source[0] = 1;
        for(int i = 1; i <= 5; i ++){
            source[i] = sc.nextInt();
        }
        
        while(m -- > 0){
            int a = sc.nextInt();
            int b = sc.nextInt();
            int c = sc.nextInt();
            add(a, b, c);
            add(b, a, c);
        }
        
        for(int i = 0; i < 6; i ++){
            dijkstra(source[i], dist[i]);
        }
        
        Arrays.fill(st, false);
        System.out.print(dfs(1, 0, 0));//第一个位置,以第几个点为起点,当前距离之和
    }
}

 

340. 通信线路 - AcWing题库

单源最短路和二分的结合。本质上是求最大值最小,联想到二分法来求 

二分思路:

定义在[0, 1000001]这个区间中x的划分符合以下性质:

从1到n,最少经过的长度大于x的边的数量是否小于等于k。

 

AcWing 340. 通信线路 - AcWing 

import java.util.*;

public class Main{
    static int N = 1010, M = 10010 * 2, INF = 0x3f3f3f3f;
    static int n, m, k, idx;
    static int[] h = new int[N], ne = new int[M], e = new int[M], w = new int[M];
    static boolean[] st = new boolean[N];
    static Deque<Integer> q = new LinkedList<>();//双端队列
    static int[] dist = new int[N];
    
    //邻接表存储
    public static void add(int a, int b, int c){
        e[idx] = b;
        w[idx] = c;
        ne[idx] = h[a];
        h[a] = idx ++;
    }
    
    public static boolean check(int x){
        Arrays.fill(st, false);//有多组数据,每一次都要进行初始化
        Arrays.fill(dist, INF);
        
        dist[1] = 0;
        q.addLast(1);
        
        while(!q.isEmpty()){
            int t = q.pollFirst();
            
            if(st[t]) continue;
            st[t] = true;
            
            for(int i = h[t]; i != -1; i = ne[i]){
                int j = e[i];
                int v = w[i] > x ? 1 : 0;
                if(dist[j] > dist[t] + v){
                    dist[j] = dist[t] + v;
                    
                    if(v == 0) q.addFirst(j);
                    else q.addLast(j);
                }
            }
        }
        return dist[n] <= k;
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        k = sc.nextInt();
        
        Arrays.fill(h, -1);//初始化队头
        
        while(m -- > 0){
            int a = sc.nextInt();
            int b = sc.nextInt();
            int c = sc.nextInt();
            add(a, b, c);//无向图
            add(b, a, c);
        }
        
        //二分
        int l = 0, r = (int)1e6 + 1;
        while(l < r){
            int mid = l + r >> 1;
            if(check(mid)) r = mid;
            else l = mid + 1;
        }
        
        if(r == 1e6 + 1) r = -1;
        System.out.print(r);
    }
}

 

342. 道路与航线 - AcWing题库

拓扑排序和dijkstra相结合

2024-01-30(树与图的深度优先遍历、广度优先遍历、拓扑排序)-CSDN博客 

 

/***
 * 1.首先输入双向道路,然后将他们分块,用dfs求出所有的连通块,用id[]存这些点所在的
 *   连通块的编号,用block[]存这个连通块中有哪些点
 * 2.然后输入单向航线,将所有连通块的入度统计出来
 * 3.将所有的距离初始化为INF,起点S初始化为0,进行拓扑排序,在topsort函数中,将所有
 *   入度是0的连通块加入到队列当中,然后每次弹出队首的编号t,将这个t进行dijkstra
 * 4.在dijkstra中,创建一个优先队列(小根堆)将这个连通块中所有的点都加入到优先队列
 *   中,每次弹出的队首是一个PII(distance,num),如果已经标记过就continue,否则就
 *   标记为true,枚举它的所有出边,如果dist[j] > distance + w[i],那么进行更新。然后
 *   判断一下,如果id[j]和id[num]两个点是一样的说明在同一个连通块中,那么加入优先队列
 *   如果id[j]!=id[num]那么说明是单项航线,那么将这个点j所对应的连通块的入度减1,当
 *   这个连通块的入度为0的时候,就把它加入到全局变量中去
 **/
 
import java.util.*;
import java.io.*;

class PII implements Comparable<PII>{
    int distance, num;
    public PII(int distance, int num){
        this.distance = distance;
        this.num = num;
    }
    
    public int compareTo(PII o){
        return distance - o.distance;
    }
}

public class Main{
    static int N = 25010, M = 150010, INF = 0x3f3f3f3f;
    //n表示所有的点,mr表示双向道路,mp表示单项航线,S表示起点,cnt表示连通块的编号
    static int n, mr, mp, idx, S, cnt;
    static int[] h = new int[N], e = new int[M], ne = new int[M], w = new int[M];
    static boolean[] st = new boolean[N];
    static Queue<Integer> q = new LinkedList<>();
    static int[] id = new int[N];//这个点属于哪个连通块
    static List<Integer>[] block = new ArrayList[N];//这个连通块中有哪些点
    static int[] din = new int[N];//连通块的入度
    static int[] dist = new int[N];//距离
    
    //邻接表存储
    public static void add(int a, int b, int c){
        e[idx] = b;
        w[idx] = c;
        ne[idx] = h[a];
        h[a] = idx ++;
    }
    
    //u表示点的编号,cnt表示连通块的编号
    public static void dfs(int u, int cnt){
        id[u] = cnt;
        
        //如果这个连通块还没有,那么就建立一个新的block
        if(block[cnt] == null) block[cnt] = new ArrayList<>();
        block[cnt].add(u);//把这个点加入到这个连通块中
        
        //遍历这个点的所有邻接点
        for(int i = h[u]; i != -1; i = ne[i]){
            int j = e[i];
            //这个邻接点所属的连通块的编号为0,也就是说还没有进行分配,那么进行dfs
            if(id[j] == 0) dfs(j, cnt);
        }
    }
    
    public static void topsort(){
        Arrays.fill(dist, INF);
        dist[S] = 0;
        
        //所有入度为0的连通块加入队列
        for(int i = 1; i <= cnt; i ++){
            if(din[i] == 0) q.offer(i);
        }
        
        while(!q.isEmpty()){
            int t = q.poll();
            dijkstra(t);//t表示连通块的编号
        }
    }
    
    //堆优化版的dijkstra算法
    public static void dijkstra(int bid){//bid表示连通块的编号
        PriorityQueue<PII> queue = new PriorityQueue<>();//优先队列
        //循环遍历这个连通块里的所有点,并把它们加入优先队列中
        for(int ver : block[bid]) queue.offer(new PII(dist[ver], ver));
        
        while(queue.size() != 0){
            PII t = queue.poll();//取出队头
            
            int num = t.num;
            int distance = t.distance;
            
            if(st[num]) continue;
            st[num] = true;
            
            for(int i = h[num]; i != -1; i = ne[i]){
                int j = e[i];
                
                //判断不属于一个连通块
                if(id[j] != id[num] && -- din[id[j]] == 0) q.offer(id[j]);
                if(dist[j] > distance + w[i]){
                    dist[j] = distance + w[i];
                    //判断一下是否同属于一个连通块
                    if(id[j] == id[num]) queue.offer(new PII(dist[j], j));
                }
            }
        }
    }
    
    public static void main(String[] args)throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] s = br.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        mr = Integer.parseInt(s[1]);
        mp = Integer.parseInt(s[2]);
        S = Integer.parseInt(s[3]);
        
        Arrays.fill(h, -1);//初始化队头
        
        //输入双向航线
        while(mr -- > 0){
            String[] arr = br.readLine().split(" ");
            int a = Integer.parseInt(arr[0]);
            int b = Integer.parseInt(arr[1]);
            int c = Integer.parseInt(arr[2]);
            add(a, b, c);
            add(b, a, c);
        }
        
        //找出所有点所属的连通块,并且每个连通块中有哪些点
        for(int i = 1; i <= n; i ++){
            //如果这个点还没有找到所属的连通块,那么说明它属于另一个连通块,所以连通块的编号要加1
            if(id[i] == 0) dfs(i, ++ cnt);
        }
        
        //接下来读入单向航线
        while(mp -- > 0){
            String[] str = br.readLine().split(" ");
            int a = Integer.parseInt(str[0]);
            int b = Integer.parseInt(str[1]);
            int c = Integer.parseInt(str[2]);
            add(a, b, c);
            din[id[b]] ++;//将编号为b的点所属的连通块的入度加1
        }
        
        //开始进行拓扑排序
        topsort();
        
        for(int i = 1; i <= n; i ++){
            if(dist[i] > INF / 2) System.out.println("NO PATH");
            else System.out.println(dist[i]);
        }
    }
}

 

341. 最优贸易 - AcWing题库

单源最短路和dp的结合 

dp问题绝大部分上是拓扑图上的最短(最长)路径问题

 AcWing 341. 最优贸易 - AcWing

import java.util.*;
import java.io.*;

public class Main{
    //这里M取这个值是因为最坏的情况下都是无向边,我们还要建立反向图
    static int N = 100010, M = 2000010, INF = 0x3f3f3f3f;
    static int n, m, idx;
    static int[] hl = new int[N], hr = new int[N], e = new int[M], ne = new int[M];
    static int[] w = new int[N];//点的权重
    static int[] dmin = new int[N], dmax = new int[N];
    static boolean[] st = new boolean[N];
    
    public static void add(int[] h, int a, int b){
        e[idx] = b;
        ne[idx] = h[a];
        h[a] = idx ++;
    }
    
    public static void spfa(int[] h, int[] dist, int type){
        Queue<Integer> q = new LinkedList<>();//循环队列
        
        if(type == 0){
            //求最小值
            Arrays.fill(dist, INF);
            dist[1] = w[1];
            q.offer(1);
        }else{
            //求最大值
            Arrays.fill(dist, -INF);
            dist[n] = w[n];
            q.offer(n);
        }
        
        while(!q.isEmpty()){
            int t = q.poll();
            st[t] = false;//取出队头,st置为false
            
            for(int i = h[t]; i != -1; i = ne[i]){
                int j = e[i];
                if((type == 0 && dist[j] > Math.min(dist[t], w[j])) || (type == 1 && dist[j] < Math.max(dist[t], w[j]))){
                    if(type == 0) dist[j] = Math.min(dist[t], w[j]);
                    else dist[j] = Math.max(dist[t], w[j]);
                    
                    if(!st[j]){
                        q.offer(j);
                        st[j] = true;
                    }
                }
            }
        }
    }
    
    public static void main(String[] args)throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] s = br.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        m = Integer.parseInt(s[1]);
        
        Arrays.fill(hl, -1);//初始化队头
        Arrays.fill(hr, -1);//初始化反向队头
        
        String[] arr = br.readLine().split(" ");
        for(int i = 1; i <= n; i ++){
            w[i] = Integer.parseInt(arr[i - 1]);
        }
        
        //建图
        for(int i = 1; i <= m; i ++){
            String[] str = br.readLine().split(" ");
            int a = Integer.parseInt(str[0]);
            int b = Integer.parseInt(str[1]);
            int c = Integer.parseInt(str[2]);
            add(hl, a, b);
            add(hr, b, a);
            if(c == 2){//双向道路
                add(hr, a, b);
                add(hl, b, a);
            }
        }
        
        //求最大值是1,最小值是0
        spfa(hl, dmin, 0);
        spfa(hr, dmax, 1);
        
        int res = 0;
        for(int i = 1; i <= n; i ++){//以i为分界点
            res = Math.max(res, dmax[i] - dmin[i]);
        }
        System.out.print(res);
    }
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/425142.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解读OWASP软件保障成熟度模型SAMM

OWASP软件保证成熟度模型&#xff08;SAMM&#xff09;可为所有类型的组织分析和改进其软件安全态势提供有效和可衡量的方法。OWASP SAMM支持完整的软件生命周期&#xff0c;包括开发和获取&#xff0c;并且与技术和过程无关。 1. 简介 OWASP软件保证成熟度模型&#xff08;SA…

文生视频基础1:sora技术报告学习

sora技术报告学习 背景学后理解训练流程技术拆解编码解码扩散模型训练用数据 28号直播交流会后的一些想法自身的一点点想法 参考 原文地址&#xff1a;Video generation models as world simulators 背景 此项目的背景是基于Datawhale的关于sora技术文档的拆解和相关技术讲解…

什么是支持向量机(Support vector machine)和其原理

作为机器学习的基础算法&#xff0c;SVM被反复提及&#xff0c;西瓜书、wiki都能查到详细介绍&#xff0c;但是总是觉得还差那么点&#xff0c;于是决定自己总结一下。 一、什么是SVM&#xff1f; 1、解决什么问题&#xff1f; SVM&#xff0c;最原始的版本是用于最简单的线…

部署bpmn项目实现activiti流程图的在线绘制

本教程基于centos7.6环境中完成 github开源项目: https://github.com/Yiuman/bpmn-vue-activiti软件&#xff1a;git、docker 1. 下载源代码 git clone https://github.com/Yiuman/bpmn-vue-activiti.git2. 修改Dockerfile文件 声明基础镜像&#xff0c;将项目打包&#xff…

vue2+若依框架plus交互 路由介绍

本周及寒假 参加了校企合作的工程过程管理&#xff0c;和学长学姐一起写项目&#xff0c;之前学了vue也没有应用&#xff0c;然后对框架很多组件的用法不太了解&#xff0c;前期耽误了一些时间。 框架模块 首先是框架模块的介绍 api存了一些系统管理及发送请求的方法 例如p…

智能驾驶规划控制理论学习04-基于车辆运动学的规划方法

目录 一、线性二自由度汽车模型&#xff08;自行车模型&#xff09; 1、二自由度模型概述 2、不同参考点下的状态空间方程 3、前向仿真 二、运动基元生成方法 1、杜宾斯曲线&#xff08;Dubins Curve&#xff09; 2、Reeds Shepp Curve 三、多项式曲线&#xff08;Poly…

redis7.2.2|Dict

文章目录 StructredisDBdictdictTypedictEntry 宏定义散列函数散列冲突dictEntry pointer bit tricks[指针位技巧]API implementation_dictReset_dictInitdictCreatedictGetHashdictSetKeydictSetValdictSetNextdictGetNextdictGetValdictGetKey_dictCleardictEmptydictRelease…

五、西瓜书——集成学习

1.个体与集成 集成学习通过将多个学习器进行结合,常可获得比单一学习器显著优越的泛化性能&#xff0c;这对“弱学习器”(weak learner)尤为明显因此集成学习的很多理论研究都是针对弱学习器进行的而基学习器有时也被直接称为弱学习器。 要获得好的集成个体学习器应“好而不同”…

详解JavaScript的函数

详解 JavaScript 的函数 函数的语法格式 创建函数/函数声明/函数定义 function 函数名(形参列表) { 函数体 return 返回值; // return 语句可省略 } 函数调用 函数名(实参列表) // 不考虑返回值 返回值 函数名(实参列表) // 考虑返回值 示例代码 //定义的没有参数列表&am…

5个好玩神奇还免费的工具网站收藏不后悔-搜嗖工具箱

生命倒计时 http://www.thismuchlonger.com 这是一个相哇塞的网站&#xff0c;可以让我们静下心来好好想想我们来这个世界究竟为了什么&#xff0c;因为当我们作为命运的主宰者。敲打键盘设定好自己一生长度的时候&#xff0c;我们的剩余寿命已经成绝对值&#xff0c;一旦生命…

mysql5.7配置主从

原理&#xff1a; MySQL主从复制的工作原理如下:1. 主服务器产生Binlog日志当主服务器的数据库发生数据修改操作时,如INSERT、UPDATE、DELETE语句执行,主服务器会记录这些操作的日志信息到二进制日志文件中。2. 从服务器读取Binlog日志 从服务器会向主服务器发送请求,主服务器把…

Linux网络编程——socket 通信基础

Linux网络编程——socket 通信基础 1. socket 介绍2. 字节序2.1 简介2.2 字节序举例2.3 字节序转换函数 3. socket 地址3.1 通用 socket 地址3.2 专用 socket 地址 4. IP地址转换&#xff08;字符串ip -> 整数&#xff0c;主机、网络字节序的转换 &#xff09;5. TCP 通信流…

智能驾驶规划控制理论学习05-车辆运动学规划案例分析

目录 案例一——Hybrid A*&#xff08;基于正向运动学&#xff09; 1、基本思想 2、 实现流程 3、启发函数设计 4、分析扩张&#xff08;Analytic Expansions&#xff09; 5、分级规划&#xff08;Hierarchical planning&#xff09; 案例二——State Lattice Planning&…

Vue3快速上手(十六)Vue3路由传参大全

Vue3路由传参 一、传参的多种方式 1.1 拼接方式 这种方式适合传递单个参数的情况&#xff0c;比如点击查看详情&#xff0c;传个id这样的场景 传参&#xff1a; <RouterLink to"/person?id1" active-class"active">person</RouterLink> …

RabbitMQ相关问题

RabbitMQ相关问题 一、RabbitMQ的核心组件和工作原理&#xff1f;二、如何保证消息可靠投递不丢失的&#xff1f;三、RabbitMQ如何保证消息的幂等性&#xff1f;四、什么是死信队列&#xff1f;死信队列是如何导致的&#xff1f;五、RabbitMQ死信队列是如何导致的&#xff1f;六…

PDF 解析问题调研

说点真实的感受 &#xff1a;网上看啥组件都好&#xff0c;实际测&#xff0c;啥组件都不行。效果好的不开源收费&#xff0c;开源的效果不好。测试下来&#xff0c;发现把组件融合起来&#xff0c;还是能不花钱解决问题的&#xff0c;都是麻烦折腾一些。 这里分享了目前网上能…

数据结构 第3章 栈、队列和数组(一轮习题总结)

第3章 栈、队列和数组 3.1 栈3.2 队列3.3 栈与队列的应用3.4 数组和特殊矩阵 3.1 栈&#xff08;1 10 11 20&#xff09; 3.2 队列&#xff08;6 12 14 17&#xff09; 3.3 栈与队列的应用&#xff08;6 11&#xff09; 3.4 数组和特殊矩阵 3.1 栈 T1 栈和队列具有相同的逻辑…

一周学会Django5 Python Web开发-Django5详细视图DetailView

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计28条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

Linux-信号2

文章目录 前言一、信号是如何保存的&#xff1f;int sigemptyset(sigset_t *set);int sigfillset(sigset_t *set);int sigaddset (sigset_t *set, int signo);int sigdelset(sigset_t *set, int signo);int sigismember&#xff08;const sigset_t *set, int signo);int sigpen…

leetcode 长度最小的子数组

在本题中&#xff0c;我们可以知道&#xff0c;是要求数组中组成和为target的最小子数组的长度。所以&#xff0c;我们肯定可以想到用两层for循环进行遍历&#xff0c;然后枚举所有的结果进行挑选&#xff0c;但这样时间复杂度过高。 我们可以采用滑动窗口&#xff0c;其实就是…