算法提高-图论-单源最短路的建图方式

news2024/11/26 21:46:11

单源最短路的建图方式

  • 单源最短路的建图方式
    • AcWing 1129. 热浪
    • AcWing 1128. 信使
    • AcWing 1127. 香甜的黄油
    • AcWing 1126. 最小花费
    • AcWing 920. 最优乘车
    • AcWing 903. 昂贵的聘礼

单源最短路的建图方式

AcWing 1129. 热浪

#include <iostream>
#include <cstring>

using namespace std;

const int N = 2500 + 10, M = 6200 * 2 + 10;
int q[N], dist[N];
bool st[N];
int e[M], h[N], w[M], ne[M], idx;//理解链表存储图的本质,h只需要开N,与节点数相同
int n, m, S, T;

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

void spfa()
{
    memset(st, 0, sizeof st);
    
    memset(dist, 0x3f, sizeof dist);
    
    dist[S] = 0;//S是起点,起点到自己的距离为0
    
    int hh = 0, tt = 1;//默认S先占一个位置,因此tt要从1开始,同时这也满足进入while循环的条件hh!=tt
    q[0] = S;
    st[S] = true;
    
    
    while (hh != tt)//循环队列不是<= 而是!
    {
        int t = q[hh ++ ];
        if (hh == N) hh = 0;
        st[t] = false;
        
        for (int i = h[t]; ~i; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > dist[t] + w[i])
            {
                dist[j] = dist[t] + w[i];
                if (!st[j])
                {
                    q[tt ++ ] = j;
                    if (tt == N) tt = 0;//循环队列,st数组的存在队列里面最多存储N个点,一个点可能多次入队,
                                        //我们不知道大概这个队列应该开多大,同时为了节省空间我们用循环队列
                    st[j] = true;
                }
            }
        }
    }
    
}
int main ()
{
    cin >> n >> m >> S >> T;
    
    memset(h, -1, sizeof h);//这个不能放在spfa里面,必须在add之前就初始化好h数组。。之前傻逼了
    
    for (int i = 0; i < m; i ++ )
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c), add(b, a, c);
    }
    
    spfa();
    
    cout << dist[T];
    return 0;
}

AcWing 1128. 信使

在这里插入图片描述

#include <iostream>
#include <cstring>

using namespace std;

const int N = 110, INF = 0x3f3f3f3f;

int n, m;
int d[N][N];

int main()
{
    cin >> n >> m;
    memset(d, 0x3f, sizeof d);
    
    for (int i = 1; i <= n; i ++ ) d[i][i] = 0;//初始化,每个点作为源点到他自己的距离为0
    
    for (int i = 0; i < m; i ++ )
    {
        int a, b, c;
        cin >> a >> b >> c;
        d[a][b] = d[b][a] = min(d[a][b], c);//最短路问题有重边,取最短的即可
    }
    
    for (int k = 1; k <= n; k ++ )
        for (int i = 1; i <= n; i ++ )
            for (int j = 1; j <= n; j ++ )
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);//floyd本质是动态规划,划分子集的时候可以以最后到达j前的最后一个点是k来划分,k这一维可以省略
    
    int ans = 0;
    for (int i = 1; i <= n; i ++ )
        if (d[1][i] == INF)
        {
            ans = -1;
            break;
        }
        else ans = max(ans, d[1][i]);//不是ans +=  d[1][i],因为最远的的i点都送到了,其他的点也肯定送到了,题目说了信使送信是扩散的
    
    cout << ans;
    return 0;
}

AcWing 1127. 香甜的黄油

建图 找出一个牧场,它到其他牧场的距离之和最小

//建图 找出一个牧场,它到其他牧场的距离之和最小

#include <iostream>
#include <cstring>

using namespace std;

const int N = 800 + 10, M = 1450 * 2 + 10, INF = 0x3f3f3f3f;

int n, p, m;
int id[510];
int e[M], w[M], ne[M], h[N], idx;//这里定义的时候按照牧场数定义,本质求的还是牧场之间的最短路,奶牛只不过和牧场之间有一些映射关系罢了
int q[N], st[N];//st一般如果只有一组测试数据不用多次初始化
int dist[N];


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

int spfa(int start)
{
    memset(dist, 0x3f, sizeof dist);
    
    int hh = 0, tt = 1;
    q[0] = start, dist[start] = 0, st[start] = true;
    
    while (hh != tt)
    {
        int t = q[hh ++ ];
        st[t] = false;
        if (hh == N) hh = 0;
        
        for (int i = h[t]; ~i; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > dist[t] + w[i])
            {
                dist[j] = dist[t] + w[i];
                if (!st[j])
                {
                    q[tt ++ ] = j;
                    if (tt == N) tt = 0;
                    st[j] = true;
                }
            }
        }
    }
    
     int ans = 0;
     
    // for (int i = 0; i < n; i ++ )
    // ans += dist[id[i]];
    
    for (int i = 0; i < n; i ++ )
    {
        int j = id[i];
        if (dist[j] == INF) return INF;//不知道为啥非要这么特判,题目也没说有的不可达
        ans += dist[j];
    }
     return ans;
}

int main ()
{
    cin >> n >> p >> m;
    for (int i = 0; i < n; i ++ ) cin >> id[i];
    
    memset(h, -1, sizeof h);
    for (int i = 0; i < m; i ++ ) 
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c), add(b, a, c);
    }
    
    int ans = INF;
    //因为牧场的编号是从1开始的,所以遍历要从1开始而不是0
    for (int i = 1; i <= p; i ++ ) ans = min(ans, spfa(i));
    
    cout << ans;
    return 0;
}


AcWing 1126. 最小花费

我是这么理解的,djsktra是一个贪心的思想,加法里面不能加负数我就不说了
求乘法最大值的时候为什么边权必须0-1,因为在乘法最大值里面有一个边权大于1的话那不就等价于求加法最小值的时候有一个边权为负数的么,dj是贪心的思想,每次出队的时候必须都是最值不能在改变了,而乘法最大值中边权大于1会破坏这个贪心的思路。
在这里插入图片描述
一开始建图没想到是无向图debug了好久,甚至以为是double精度问题

#include <iostream>
#include <cstring>

using namespace std;

const int N = 2010;//用邻接表存储图的时候不需要定义边的条数,有重边的情况下根据题意去最大值或最小值即可

bool st[N];
double dist[N];
double g[N][N];

int n, m, S, T;

void  dijkstra()
{
    dist[S] = 1;
    //st[S] = true;不能把源点先变为true,因为我们还需要源点去更新源点周围的点
                                  //n个点,在边权满足条件的情况下,每个点都要遍历一次,因此需要遍历n次
    for (int i = 1; i <= n; i ++ )//for (int i = 0; i < n; i ++ ) 循环n次就行了,下标从1和0开始都可以,但是下面的for涉及下标了,看题意是下标从0还是1开始
    {
        int t = -1;                  //j是具体的点的下标,题目说了 下标>=1   
        for (int j = 1; j <= n; j ++ )//贪心:找到当前没确定的点 且 离源点最近的点
        {
            if (!st[j] && (t == -1 || dist[t] < dist[j]))
                t = j;
        }
        st[t] = true;
        
        for (int j = 1; j <= n; j ++ )
        {
            dist[j] = max(dist[j], dist[t] * g[t][j]);//动态规划,用距离源点最近的点去更新其他点到源点的距离
        }
    }
}


int main ()
{
    cin >> n >> m;
    for (int i = 0; i < m; i ++ )
    {
        int a, b, c;
        cin >> a >> b >> c;
        
        g[a][b] = g[b][a] = max(g[a][b], (100.0 - c) / 100);
        //g[a][b] = max(g[a][b], (double)(100.0 - c) / 100);
        //double z = (100.0 - c) / 100;
        //g[a][b] = g[b][a] = max(g[a][b], z);
    }
    
    cin >> S >> T;
    
    dijkstra();
    
    printf("%.8lf\n", 100 / dist[T]);

    return 0;
}

AcWing 920. 最优乘车

这题的输入输出挺恶心的,对了,输入小于10万就可以用cin
getline
sstream
将一辆车可以到达的所有站点之间连接都连接一条边,那就是要cn2条边具体我描述的不太好,可以去看这题的视频讲解。
在这里插入图片描述

#include <iostream>
#include <cstring>
#include <sstream>
#include <cstdio>

using namespace std;

const int N = 510, INF = 0x3f3f3f3f;
bool g[N][N];
int stop[N];
int q[N], dist[N];
int n, m;

void bfs ()
{
    memset(dist, 0x3f, sizeof dist);
    int hh = 0, tt = 0;
    q[0] = 1;
    dist[1] = 0;//dist记录的是从源点到该点需要乘坐多少次大巴,从1号点到1号点在只需要乘坐0次大巴
    while (hh <= tt)
    {
        int t = q[hh ++ ];
        
        for (int i = 1; i <= n ; i ++ )//公交站牌的下标是从1开始的不是0
        {
            if (g[t][i] && dist[i] > dist[t] + 1)
            {
                dist[i] = dist[t] + 1;
                q[++ tt] = i;
            }
        }
    }
}

int main ()
{
    cin >> m >> n;//这题是先输入m,在输入n比较恶心
    string line;
    getline(cin, line);//将第一行的换行接受掉
    
    while (m -- )
    {
        getline(cin, line);//相比于cin,这是读一整行可以读取到空格换行等
        stringstream ssin(line);//把字符串转化为int
        int cnt = 0, p;
        while (ssin >> p)  stop[cnt ++ ] = p;
        
        for (int i = 0; i < cnt; i ++ )
            for (int j = i + 1; j < cnt; j ++ )
             g[stop[i]][stop[j]] = true;
    }
    
    bfs();
    
    if (dist[n] == INF) puts("NO");
    else cout << max(dist[n] - 1, 0);//题目要输出的是换乘次数 如果换乘次数为0,则dist[n] - 1 = -1(因为只用一辆车到达目的地的换乘次数是0,但是乘坐的不同大巴种类为1)
                                     //,但题目要输出的是0 ,因此要特判一下
    
    return 0;
}

AcWing 903. 昂贵的聘礼

w数组很精髓,level数组很牛逼,虚拟源点结合w数组更nb,同时注意dijkstra里面的for循环下标的含义,到底是控制循环次数,还是真正映射的是下标

#include <iostream>
#include <cstring>

using namespace std;

const int N = 110, INF = 0x3f3f3f3f;

bool st[N];
int w[N][N], dist[N], level[N];
int m, n;


int dijkstra(int down, int up)
{
    
    memset(dist, 0x3f, sizeof dist);
    memset(st, 0, sizeof st);//不知道这里为什么会wa,明明其实一般如果没有多组数据不需要这个初始化,全局的st默认就是false
    //st[0] = true;经常犯这个错,因为我们需要用源点来更新它周围的点到它的距离,dj其实就是dfs,只不过权值不是1罢了
    dist[0] = 0;
    for (int i = 1; i <= n + 1; i ++ )//多了一个虚拟源点,因此要循环n + 1次才能确定n+1件物品到源点的最短距离,x加上虚拟源点一共有n + 1个物品,x
    {                                 //dj贪心的思想就是每次循环都可以确定一个节点到源点的最短距离,再用这个节点去更新它到其他点的距离
        int t = -1;
        for (int j = 0; j <= n; j ++ )//这里遍历的时候遍历的是编号,而不是保证次数,题目编号下标从1开始,但是我们虚拟源点的下标是0
        if (!st[j] && (t == -1 || dist[t] > dist[j]))
            t = j;
        st[t] = true;
        
        for (int j = 1; j <= n; j ++ )
        {
            if (level[j] >= down && level[j] <= up) dist[j] = min(dist[j], dist[t] + w[t][j]);//dp的思想
        }
    }
    
    return dist[1];
}





int main()
{
    cin >> m >> n;
    memset(w, 0x3f, sizeof w);
    
    for (int i = 1; i <= n; i ++ )w[i][i] = 0; //用第i个物品换第i个物品需要额外+0元
    
    for (int i = 1; i <= n; i ++ )
    {
        int price, cnt;
        cin >> price >> level[i] >> cnt;
        w[0][i] = min(price, w[0][i]);//可以不用min,但以防万一么 虽然我不知道为什么要取min题目没说会输入重复数据,但这个意思就是什么物品都不带换第i个物品需要它自身原来的价格

        while (cnt -- )
        {
            int id, cost;
            cin >> id >> cost;
            
            //w[id][i] =  cost;
            w[id][i] = min(w[id][i], cost);// 可以不用min,但以防万一么    用序号为id的物品换物品i需要+cost元
        }
    }
    
    int res = INF;
    //最终需要换的物品为物品1,因此我们以物品1为基底,遍历“图"可以到达的节点(即可以使用的物品有哪些)
    for (int i = level[1] - m; i <= level[1]; i ++ ) res = min(res, dijkstra(i, i + m));
    
    cout << res << endl;
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安装OpenWrt到电脑,安装包选哪个?

https://downloads.openwrt.org/releases/22.03.5/targets/x86/ releases发行&#xff0c;targets目标&#xff1b; —————————————— 64&#xff1a;具有64位功能的计算机&#xff1b; generic&#xff1a;一般的&#xff0c;通用的&#xff0c;仅32位计算机&…

学习Vue这一个就够

1、淘宝镜像 1: 解释一下 npm 为什么要配置淘宝镜像原因&#xff1a;因为node.js 默认使用的是国外的网站 。国内访问有一个跨国内局域网的操作。所以就会有时候很慢。这就跟为什么网站的静态资源有些会使用CDN 加速一样的淘宝镜像是什么&#xff1f;就是npm 很多的插件淘宝已经…

docker cgroub

docker 的资源管理 1、cpu的资源控制 一&#xff1a;设置cpu的资源上限 cd /sys/fs/cgroup/cpu/docker/ cpu 的占用量达到100% cpu 设置一半50% 2. 设置cpu资源占用比&#xff08;设置多个容器才有用&#xff09; docker run -itd --name c3 --cpu-shares 512 centos:7 do…

springboot+mybatis实现删除(二)

一&#xff0c;XML映射文件和动态SQL XML映射文件的名称与Mapper接口名称一致&#xff0c;并且将XML映射文件和Mapper接口放置在相同包下&#xff08;同包同名&#xff09;&#xff0c;右键创建目录/分隔&#xff0c;例&#xff1a;com/baidu/crm XML映射文件的namespace属性为…

工程训练 -江苏海洋大学-mooc-最终答案

这不点赞评论一下嘛&#xff1f;&#xff1f;&#xff1f;呜呜呜 判断题&#xff08;共217道&#xff09; 1.舂实模样周围及砂箱边或狭窄部分的型砂&#xff0c;通常采用砂舂的平头端舂砂。 2.造型时&#xff0c;分型面上通常使用的是面砂&#xff0c;覆盖模样的则使用背砂。 3…

【微服务】springboot整合swagger多种模式使用详解

目录 一、前言 1.1 编写API文档 1.2 使用一些在线调试工具 1.3 postman 1.4 swagger 二、swagger简介 2.1 背景 2.2 swagger优缺点 2.2.1 swagger优点 2.2.2 swagger缺点 2.2.3 swagger使用场景 三、swagger常用的几种整合模式 3.1 swagger2 3.2 knife4j 3.2.1 k…

《设计模式》之命令模式

文章目录 1、定义2、动机3、类结构4、优缺点5、总结6、代码实现(C) 1、定义 将一个请求封装为一个对象&#xff0c;从而使你可用不同的请求对客户端进行参数化&#xff1b;对请求排队或记录请求日志&#xff0c;以及支持可撤销的操作。 2、动机 在软件构建过程中&#xff0c…

虚拟内存和物理内存:概念、原理和应用

目录 概述1. 概念2. 原理3. 设计寻位原理4. 应用场景结论 概述 当你使用计算机时&#xff0c;内存是一个非常重要的资源。它用于存储正在运行的程序和数据&#xff0c;确保系统的正常运行。在计算机系统中&#xff0c;存在着虚拟内存和物理内存的概念&#xff0c;它们共同协作…

Docker Gitlab Container Registry配置

文章目录 前言一、Registry是什么二、步骤配置gitlab.rb文件修改docker-compose.yaml文档验证推送镜像 总结 前言 找了很多资料包括官网1都没有发现比较清楚的配置registry的方法&#xff0c;自己摸索了半天发现其实通过简单设置就能够配置好Container Registry。 之所以在题…

【Docker】3.Docker Registry

文章目录 Docker RegistryDocker Registry CommandImage Command NginxNginx System installNginx Config Container CommandCreate My DegistryBusyBox腾讯云镜像仓库搭建 Docker Registry 镜像仓库负责存储、管理、分发镜像&#xff0c;并且提供了登录认证的能力&#xff0c…

LeetCode_二叉树_DFS_中等_129.求根节点到叶节点数字之和

目录 1.题目2.思路3.代码实现&#xff08;Java&#xff09; 1.题目 给你一个二叉树的根节点 root &#xff0c;树中每个节点都存放有一个 0 到 9 之间的数字。 每条从根节点到叶节点的路径都代表一个数字&#xff1a;例如&#xff0c;从根节点到叶节点的路径 1 -> 2 -> …

【计算机网络】IP 地址处理函数

目录 1.struct sockaddr_in的结构 2.一般我们写的结构 3.常见的“点分十进制” 到 ” uint32_t 的转化接口 3.1. inet_aton 和 inet_ntoa &#xff08;ipv4&#xff09; 3.2. inet_pton 和 inet_ntop (ipv4 和 ipv6&#xff09; 3.3. inet_addr 和 inet_network 3…

人工智能-深度学习-科研神器推荐

根据知乎问题 有没有什么可以节省大量时间的 Deep Learning 效率神器&#xff1f; 的回答&#xff0c;筛选整理出一些深度学习科研神器。包括参数优化、数据可视化、模型部署蒸馏剪枝等。收录到 人工智能-深度学习-科研神器推荐https://​www.webhub123.com/#/home/detail?p4O…

vue监听缓存数据(localStorage)

方法&#xff1a;可以重写localStorage的setItem方法&#xff0c;当调用setItem方法设置新值的时候&#xff0c;会new Event(‘setItemEvent’) 用window.dispatchEvent()这个方法来派发一个事件&#xff0c;让window去监听 以下demo实现的是 一个页面获取诗句 然后将获取的数据…

【P51 】JMeter 聚合报告(Aggregate Report)

文章目录 一、聚合报告&#xff08;Aggregate Report&#xff09;参数说明二、准备工作三、测试计划设计 一、聚合报告&#xff08;Aggregate Report&#xff09;参数说明 可以查看事务或者取样器在某个时间范围内执行的汇总结果 使用场景&#xff1a;用于评估测试结果 使用…

2023-06-07 stonedb-包含内连接外连接派生表in子查询和聚合-查询结果错误-分析问题的思路

摘要: 最近在处理stonedb的一个包含内连接包含内连接外连接派生表in子查询和聚合的查询出错的问题, 逻辑非常复杂, 包含的操作符非常多. 本文首先从顶层设计出发, 指出如何分析如此复杂的问题。 查询SQL: SELECTB.company_id,上划日 ud_type,2 sort_no,合计 fiscal_date,DAT…

输入java -version 命令行没反应的简单解决办法【亲测有效】

&#x1f4a7; 记录一下今天遇到的 b u g \color{#FF1493}{记录一下今天遇到的bug} 记录一下今天遇到的bug&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微风撞见云的博客&#x1f390; &#x1f433; 数据结构与算法…

qemu+buildroot+linux arm64操作系统虚拟化-宿主系统wsl2

文章目录 1.qemu2.buildroot配置编译 3.linux kernel下载交叉编译工具链 linux kernel 5.16配置内核config_kernel.shbuild_kernel.sh 4.启动虚拟机start_qemu.sh参数解释运行 环境&#xff1a; wls2、qemu8.2、buildroot、linuxkernel 1.qemu https://buildroot.org/download…

Python知识点:lambda 表达式

大家好&#xff0c;欢迎来到 Crossin的编程教室 &#xff01; Python 是一门简洁的语言&#xff0c;lambda 表达式则充分体现了 Python 这一特点。 lambda 表达可以被看做是一种匿名函数。它可以让你快速定义一个极度简单的单行函数。譬如这样一个实现三个数相加的函数&#xf…

学会使用perf性能分析工具(含移植到开发板)

文章目录 一、在ubuntu中使用apt包下载Perf二、使用源码安装Perf&#xff0c;并移植到arm-linux环境下三、使用perf四、Perf的功能介绍 系统&#xff1a;Ubuntu18.04系统 内核版本&#xff1a;5.4.0-150-generic&#xff08;通过uname -r查看&#xff09; 一、在ubuntu中使用ap…