【Acwing—单源最短路:建图】

news2025/1/16 20:15:13

y总说,图论题的难点不在于打板子,而是建图的过程

个人觉得,建图的过程分成以下阶段:

1.确定结点的意义

2.确定边权的意义

结点一般都很显然,但是边权的意义我们一般把它设成对答案(或需要维护的东西)的贡献

具体看以下的例子:

1.热浪

1129. 热浪 - AcWing题库

题意:

思路:

跑一遍最短路就行,spfa,dij,floyd都行

Code:

#include <bits/stdc++.h>
using namespace std;
const int mxn=1e4+10,mxe=1e4+10,mnf=0x3f3f3f3f;
struct ty{
    int to,next,w;
}edge[mxe<<1];
queue<int> q;
int n,m,s,t,u,v,w,tot=0;
int head[mxn],dis[mxn],vis[mxn];
void add(int u,int v,int w){
    edge[tot].w=w;
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void init(){
    tot=0;
    for(int i=0;i<=n;i++){
        head[i]=-1;
        vis[i]=0;
        dis[i]=mnf;
    }
    while(!q.empty()) q.pop();
}
void spfa(){
    dis[s]=0;
    vis[s]=1;
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];~i;i=edge[i].next){
            if(dis[edge[i].to]>dis[u]+edge[i].w){
                dis[edge[i].to]=dis[u]+edge[i].w;
                if(!vis[edge[i].to]){
                    vis[edge[i].to]=1;
                    q.push(edge[i].to);
                }
            }
        }
    }
}
int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin>>n>>m>>s>>t;
    init();
    for(int i=1;i<=m;i++){
        cin>>u>>v>>w;
        add(u,v,w);
        add(v,u,w);
    }
    spfa();
    if(dis[t]==mnf) cout<<-1<<'\n';
    else cout<<dis[t]<<'\n';
}

2.信使

1128. 信使 - AcWing题库

题意:

这个就是跑一遍最短路,预处理一下dis数组,然后去看dis最大值就行

Code:

#include <bits/stdc++.h>
using namespace std;
const int mxn=2e2+10,mxe=2e2+10,mnf=0x3f3f3f3f,inf=0xc0c0c0c0;
struct ty{
    int to,next,w;
}edge[mxe<<1];
queue<int> q;
int n,m,x,y,w,tot=0;
int head[mxn],dis[mxn],vis[mxn];
void add(int u,int v,int w){
    edge[tot].w=w;
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void init(){
    tot=0;
    for(int i=0;i<=n;i++){
        vis[i]=0;
        head[i]=-1;
        dis[i]=mnf;
    }
    while(!q.empty()) q.pop();
}
void spfa(){
    dis[1]=0;
    vis[1]=1;
    q.push(1);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];~i;i=edge[i].next){
            if(dis[edge[i].to]>dis[u]+edge[i].w){
                dis[edge[i].to]=dis[u]+edge[i].w;
                if(!vis[edge[i].to]){
                    q.push(edge[i].to);
                    vis[edge[i].to]=1;
                }
            }
        }
    }
}
int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin>>n>>m;
    init();
    for(int i=1;i<=m;i++){
        cin>>x>>y>>w;
        add(x,y,w);
        add(y,x,w);
    }
    spfa();
    int ans=inf;
    for(int i=1;i<=n;i++){
        if(dis[i]==mnf){
            cout<<-1<<'\n';
            return 0;
        }
        ans=max(ans,dis[i]);
    }
    cout<<ans<<'\n';
}

 3.香甜的黄油

1127. 香甜的黄油 - AcWing题库

枚举就行,枚举奶油放在哪个点上,每个点都去跑一遍最短路,然后去看奶油放在哪个点上牛牛到奶油的距离之和最小

Code:

#include <bits/stdc++.h>
using namespace std;
const int mxn=2e3+10,mxe=2e3+10,mnf=0x3f3f3f3f;
struct ty{
    int to,next,w;
}edge[mxe<<1];
struct ty2{
    int x,dis;
    bool operator< (const ty2 &a) const{
        return a.dis<dis;
    }
};
unordered_map<int,int> mp;
priority_queue<ty2> q;
int N,n,m,x,y,w,tot=0;
int head[mxn],dis[mxn],vis[mxn];
void add(int u,int v,int w){
    edge[tot].w=w;
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void init(){
    tot=0;
    mp.clear();
    for(int i=0;i<=n;i++){
        head[i]=-1;
        dis[i]=mnf;
        vis[i]=0;
    }
    while(!q.empty()) q.pop();
}
void init2(){
    for(int i=0;i<=n;i++){
        vis[i]=0;
        dis[i]=mnf;
    }
    while(!q.empty()) q.pop();
}
int dij(int s){
    init2();
    dis[s]=0;
    ty2 u;
    u.dis=dis[s],u.x=s;
    q.push(u);
    while(!q.empty()){
        ty2 u=q.top();
        q.pop();
        if(vis[u.x]) continue;
        vis[u.x]=1;
        for(int i=head[u.x];~i;i=edge[i].next){
            if(vis[edge[i].to]) continue;
            if(dis[edge[i].to]>dis[u.x]+edge[i].w){
                dis[edge[i].to]=dis[u.x]+edge[i].w;
                ty2 tmp;
                tmp.dis=dis[edge[i].to];
                tmp.x=edge[i].to;
                q.push(tmp);
            }
        }
    }
    int res=0;
    for(int i=1;i<=n;i++){
        if(mp[i]){
            if(dis[i]==mnf) return mnf;
            res+=dis[i]*mp[i];
        }
    }
    return res;
}
int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin>>N>>n>>m;
    init();
    for(int i=1;i<=N;i++) cin>>x,mp[x]++;
    for(int i=1;i<=m;i++){
        cin>>x>>y>>w;
        add(x,y,w);
        add(y,x,w);
    }
    int ans=mnf;
    for(int i=1;i<=n;i++){
        ans=min(ans,dij(i));
    }
    cout<<ans<<'\n';
}

 4.最小花费

1126. 最小花费 - AcWing题库

题意:

思路:

转化为A*w1*w2*....*wn=B,即求w1*w2*....*wn最小值,其中wi为扣除的百分比

那么我们可以建图:

结点表示人

边权表示扣除的百分比

建完图后,可以发现我们要求的就是边权最小积

那么我们怎么从最小和转换到最小积:取对数就好了

lg(w1*w2*....*wn)=lgw1+lgw2+....+lgwn

因为lg函数始终是单调递增的,因此要求w1*w2*....*wn的最小值,就求lg(w1*w2*....*wn)的最小值

即求lgw1+lgw2+....+lgwn的最小值

即求lgwi的最小值

因此我们可以按照wi的大小去跑一遍最短路,然后跑的时候dist的值维护边权积就可以了

Code:

#include <bits/stdc++.h>
using namespace std;
const int mxn=2e3+10,mxe=1e5+10,mnf=0x3f3f3f3f;
struct ty{
    int to,next;
    double w;
}edge[mxe<<1];
queue<int> q;
int n,m,x,y,w,tot=0,s,t;
int head[mxn],vis[mxn];
double dis[mxn];
void add(int u,int v,double w){
    edge[tot].w=w;
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void init(){
    tot=0;
    for(int i=0;i<=n;i++){
        head[i]=-1;
        vis[i]=0;
    }
    while(!q.empty()) q.pop();
}
double spfa(int u,int v){
    dis[u]=1;
    q.push(u);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];~i;i=edge[i].next){
            if(dis[edge[i].to]<dis[u]*(1.0-edge[i].w)){
                dis[edge[i].to]=dis[u]*(1.0-edge[i].w);
                if(!vis[edge[i].to]){
                    vis[edge[i].to]=1;
                    q.push(edge[i].to);
                }
            }
        }
    }
    return dis[t];
}
int main(){
    //ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    scanf("%d%d",&n,&m);
    init();
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&w);
        add(x,y,1.0*w/100);
        add(y,x,1.0*w/100);
    }
    scanf("%d%d",&s,&t);
    printf("%.8f\n",100/spfa(s,t));
}

5.最优乘车

920. 最优乘车 - AcWing题库

题意:

 思路:

换乘次数=坐车次数-1

因此我们只需要维护坐车次数就行

首先先建图:

结点就是公交车站

边权意义就设成坐车次数

那么在同一线路上的车站之间的坐车次数都为1,因此同一线路上的车站之间都连一条边权为1的边

不同线路的车站之间的坐车次数就可以根据跑最短路来求了

时间复杂度为O(M*(N-1)*N/2)

Code:

#include <bits/stdc++.h>
using namespace std;
const int mxn=5e2+10,mxe=5e2+10,mnf=0x3f3f3f3f;
struct ty{
    int to,next,w;
}edge[mxe<<1];
queue<int> q;
string s;
int m,n,len=0,p,tot=0;
int a[mxn],head[mxn],dis[mxn],vis[mxn];
void add(int u,int v,int w){
    edge[tot].w=w;
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void init(){
    tot=0;len=0;
    s.clear();
    for(int i=0;i<=n;i++){
        head[i]=-1;
        dis[i]=mnf;
    }
    while(!q.empty()) q.pop();
}
void spfa(){
    dis[1]=0;
    vis[1]=1;
    q.push(1);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];~i;i=edge[i].next){
            if(dis[edge[i].to]>dis[u]+edge[i].w){
                dis[edge[i].to]=dis[u]+edge[i].w;
                if(!vis[edge[i].to]){
                    vis[edge[i].to]=1;
                    q.push(edge[i].to);
                }
            }
        }
    }
}
int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin>>m>>n;
    init();
    getline(cin,s);
    for(int i=1;i<=m;i++){
        len=0;
        getline(cin,s);
        stringstream ssin(s);
        while(ssin>>p) a[++len]=p; 
        for(int i=1;i<=len;i++){
            for(int j=i+1;j<=len;j++){
                add(a[i],a[j],1);
                add(a[j],a[i],1);
            }
        }
    }
    spfa();
    if(dis[n]==mnf) cout<<"NO"<<'\n';
    else cout<<dis[n]<<'\n';
}

总结:

建图的过程分成以下阶段:

1.确定结点的意义

2.确定边权的意义

结点一般都很显然,但是边权的意义我们一般把它设成对答案(或需要维护的东西)的贡献

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

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

相关文章

C++入门知识(二)

最近太忙了&#xff0c;发论文写开题&#xff0c;有两周时间没有学习C了&#xff0c;因为都是抽时间来学习&#xff0c;所以本篇博客也是零零散散的&#xff0c;接下来尽量抽时间吧 目录 六、引用 6.1 引用概念 6.2 引用特性 6.3 常引用 6.4 使用场景 6.5 传值、传引用…

并发编程(一)可见性

【并发编程三大特性】&#xff1a; 可见性 有序性 原子性&#xff08; 较复杂 &#xff09; 【线程的可见性】&#xff1a; 【一个例子认识线程的可见性】&#xff1a; import Utils.SleepHelper; import java.io.IOException;public class T01_HelloVolatile {private sta…

Go中的泛型和反射以及序列化

嗨喽,小伙伴们,好几没有更新了,最近在搞一些云原生的东西,docker , k8s 搞得我暂时迷失了方向,不过我举得搞IT吗,就是在不断尝试,搞一下当下最新的技术,不然 … GO中的泛型与继承 搞过java的都知道泛型与继承,在go中也开始搞泛型与继承了(在go1.8之后) 先看代码–>> p…

【记录】PyCharm 安装 preprocess 模块(库)|| 在 PyCharm 中安装 preprocess 失败,故而在 终端 安装

preprocess.py 针对的是处理许多 文件类型。它工作的语言包括&#xff1a;C、Python、 perl、tcl、xml、javascript、css、idl、tex、fortran、php、java、shell 脚本&#xff08;bash、csh等&#xff09;和c。预处理可以作为 命令行应用程序和作为python 模块。 目录一、在 Py…

矩阵论复习提纲

矩阵论复习提纲 第一章 矩阵相似变化 1、特征值与特征向量 A ∈ Cnxn 若存在 λ ∈ C 满足 Ax λx 则 λ 为 A 的特征值 可转换为 &#xff08;λI - A&#xff09;x 0 特征多项式 &#xff1a;det(λI - A) 特征矩阵&#xff1a; λI - A 2、相似对角化 1. 判断可对角化…

VMware Fusion 13 正式版终于来了

千呼万唤&#xff0c;经历两年之久&#xff0c;VMware终于在Fusion 13正式版中支持了Apple Silicon 版Mac&#xff0c;此次发布的Fusion是Universal版本&#xff0c;也就是一个安装包同时适配Intel Mac及Apple Silicon &#xff08;M1&#xff0c;M2&#xff09;Mac。想起我两年…

疑难杂症集合(备忘)

sshd&#xff1a;no hostkeys available 解决过程: #ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key #ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key #/usr/sbin/sshd 如果上述两个文件存在&#xff0c;仍然出现这个错误&#xff0c;那么试试 chmod 600 上述两个文件。之…

01-Python的基本概念

01-Python的基本概念 Python是一种直译式&#xff08;Interpreted&#xff09;、面向对象&#xff08;Object Oriented&#xff09;的程序语言’它拥有完整的函数库’可以协助轻松地完成许多常见的工作。 所谓的直译式语言是指’直译器&#xff08;InteIpretor&#xff09;会将…

诊断故障码(Diagnostic Trouble Code-DTC)

诊断协议那些事儿 诊断协议那些事儿专栏系列文章&#xff0c;本文将由浅入深的介绍DTC&#xff08;Diagnostic Trouble Code&#xff09;。 关联文章&#xff1a; $19服务:DTCStatusMask和statusofDTC bit 定义 19服务List 文章目录诊断协议那些事儿DTC&#xff08;Diagnos…

Python pyenv install 下载安装慢(失败)完美解决

pyenv 下载原理就是将例如 Python-3.10.3.tar.xz 这样的压缩文件下载到本地缓存文件或临时文件&#xff0c;然后解压出来使用。 由于下载速度或者网不行&#xff0c;那么就跳过 pyenv 下载&#xff0c;自己下载&#xff0c;然后放到它的缓存文件&#xff0c;这样不就行了。 1…

3.np.random

1. np.random.seed np.random.seed()函数用于生成指定随机数。 seed()被设置了之后&#xff0c;np.random.random()可以按顺序产生一组固定的数组&#xff0c;如果使用相同的seed()值&#xff0c;则每次生成的随机数都相同。 如果不设置这个值&#xff0c;那么每次生成的随机数…

[附源码]计算机毕业设计JAVA基于Java的护肤品网站

[附源码]计算机毕业设计JAVA基于Java的护肤品网站 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM my…

【MySQL进阶】表的增删改查操作(CRUD)+(SQL执行顺序)

1. 新增(复制数据)2. 查询 - 进阶2.1 聚合查询2.2 group by2.3 having2.4 联合查询2.4.1 内连接2.4.2 外连接2.4.3 自连接2.4.4 子查询2.4.5 合并查询3 SQL的执行顺序(where...)1. 新增(复制数据) 语法 -- 字段名 列名 -- 将表2的数据复制到表1中 -- 两张表的结构要一样 i…

前端知识点

1.HTML 2.CSS 3.js 4.VUE 5.vUE的基本指令 6.VUE案例 7.ELEMENT HTML 设置图片 <img src"图片地址">让图片居中显示<center><img src"图片地址" width"270" height"900"></center>有序列表 <!--有序 ty…

Spring框架技术的核心与设计思想

目录 1. Spring 是什么? 1.1 什么是容器? 1.2 什么是 IoC ? 2. 传统式开发 3. 控制(权)反转式开发 4. 理解Spring 核心 - IoC 1. Spring 是什么? Spring 的全称是 Spring Framework, 它是一种开源框架, 2002 年, Rod Jahnson 首次推出了 Spring 框雏形 interface21…

[UE笔记]客户端服务器时间同步

内容系看教程所做的笔记 时间 往返时间&#xff08;RTT, Round-Trip Time&#xff09;&#xff1a;数据从客户端通过网络发送到服务器&#xff0c;再从服务器返回到客户端所需的时间。 首先客户端应当知道服务端的当前时间。 服务器启动时间总是先于客户端的&#xff0c;客户…

【学习OpenCV4】OpenCV入门精讲(C++/Python双语教学)

大家好&#xff0c;我在CSDN开的OpenCV课程已经开课了&#xff0c;入口如下&#xff1a; OpenCV入门精讲&#xff08;C/Python双语教学&#xff09; 课程开始快一周了&#xff0c;收到了广大同学们的欢迎。 &#xff08;1&#xff09;评分很高&#xff1b; &#xff08;2&#…

从Clickhouse 到 Snowflake: 云原生

云原生Clickhouse优势概述 以Clickhouse为基础&#xff0c;借鉴Snowflake等系统的设计思路&#xff0c;打造一款高性能的云原生OLAP系统&#xff0c;为用户提供多场景下的一站式的数据分析平台。 简单、易维护&#xff1a;集群管理、统一共享分布式调度服务高可用、可扩展&am…

T292114 [传智杯 #5 练习赛] 清洁工

题目描述 有一个 n\times nnn 的地块&#xff0c;一个连续 ii 分钟没人经过的地面在第 ii 分钟会落上 ii 个单位的灰&#xff0c;有人经过时不会落灰但灰也不会清零&#xff0c;在人走后第一分钟又会落上一个单位的灰&#xff0c;以此类推。你在这个 n\times nnn 的范围内移动…

深度可分离卷积神经网络与卷积神经网络

在学习语义分割过程中&#xff0c;接触到了深度可分离卷积神经网络&#xff0c;其是对卷积神经网络在运算速度上的改进&#xff0c;具体差别如下&#xff1a; 一些轻量级的网络&#xff0c;如mobilenet中&#xff0c;会有深度可分离卷积depthwise separable convolution&#…