0基础刷图论最短路 2(从ATcoder 0分到1800分)

AT最短路刷题2(本文难度rated 1000~ 1200)

题目来源:Atcoder
题目收集:
https://atcoder-tags.herokuapp.com/tags/Graph/Shortest-Path
(里面按tag分类好了Atcoder的所有题目,类似cf)
(访问需要魔法)
这算是一个题单,各位有兴趣可以按照这个顺序来刷。
我的代码仅供参考。
会提示关键性质和步骤。 部分有注释。
洛谷、知乎、可以搜到题解。

文章目录

  • AT最短路刷题2(本文难度rated 1000~ 1200)
    • 1-**Souvenir**
    • 2-**Train**
    • 3-**バスと避けられない運命**
    • 4-**Crystal Switches**
    • 5-**Shortest Path Queries 2**
    • 6- Jumping Takahashi 2
    • 7-**Skiing**
    • 8-**Wizard in Maze**

1-Souvenir

https://atcoder.jp/contests/abc286/tasks/abc286_e

双关键字最短路。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define PII pair<int,int>
#define INF 1e18int dist[301][301];
int value[301][301];
int a[301];
char s[301][301];
int n;void dijkstra(int start){vector<bool> flag(n+1);for(int i=1;i<=n;i++){dist[start][i]=INF;}dist[start][start]=0;priority_queue<PII,vector<PII>,greater<PII>> q;q.push({0,start});value[start][start]=a[start];dist[start][start]=0;while(q.size()){int u = q.top().second;q.pop();if(flag[u])continue;flag[u]=1;for(int i=1;i<=n;i++){if(i==u)continue;if(s[u][i]=='N')continue;if(dist[start][i]>dist[start][u]+1){dist[start][i] = dist[start][u]+1;value[start][i] = value[start][u] + a[i];q.push({dist[start][i],i});}else if(dist[start][i]==dist[start][u]+1 and value[start][i]<value[start][u]+a[i]){value[start][i] = value[start][u] + a[i];q.push({dist[start][i],i});}}}
}
void slove(){cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)cin>>s[i][j];for(int i=1;i<=n;i++){dijkstra(i);}int Q;cin>>Q;while(Q--){int u,v;cin>>u>>v;if(dist[u][v]==INF)cout<<"Impossible"<<endl;else cout<<dist[u][v]<<' '<<value[u][v]<<endl;}
}signed main(){slove();
}

2-Train

https://atcoder.jp/contests/abc192/tasks/abc192_e

最短路板子

/*对于每一条边:
火车发动的时间是: t = kx
所以可以开两个数组。数组1,记录 ai --> bi 城市的火车发车间隔,
数组2,记录 ai --> bi 代价如何写最短路?数组3记录 从起点到各点的最小值。
*/#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define PII pair<int,int>
#define INF 1e18const int N = 1e5+7;
struct node{int v;int w;int k;
};vector<vector<node>> g(N);
int dist[N];
bool flag[N];
int n,m;
void dijkstra(int x){for(int i=1;i<=n;i++)dist[i]=INF;dist[x]=0;priority_queue<PII,vector<PII>,greater<PII>> q;q.push({0,x});while(q.size()){int u = q.top().second;q.pop();if(flag[u])continue;flag[u]=1;for(auto i:g[u]){ //枚举能去的所有城市int v = i.v , w = i.w , k = i.k;int now = dist[u]; //当前时刻// 检查此时是不是刚好发车if(now%k==0){//如果刚好发车,那么直接加上边权if(dist[v]>dist[u]+w){dist[v] = dist[u]+w;q.push({dist[v],v});}}else{ //只能等下一班车int next = now / k + 1;now = k*next;if(dist[v]>now+w){dist[v]=now+w;q.push({dist[v],v});}}}}
}void slove(){cin>>n>>m;int x,y;cin>>x>>y;for(int i=1;i<=m;i++){int u,v,w,k;cin>>u>>v>>w>>k;g[u].push_back(node{v,w,k});g[v].push_back(node{u,w,k});}dijkstra(x);if(dist[y]==INF)cout<<-1<<endl;else cout<<dist[y]<<endl;}signed main(){slove();
}

3-バスと避けられない運命

https://atcoder.jp/contests/abc012/tasks/abc012_4

spfa板子

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define PII pair<int,int>
#define INF 1e18
const int N = 305;
int dist[N][N];
void slove(){int n,m;cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){dist[i][j]=INF;}dist[i][i]=0;}for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;dist[u][v]=w;dist[v][u]=w;}for(int k=1;k<=n;k++){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j]);}}}int ans = INF;for(int i=1;i<=n;i++){int cnt=0;for(int j=1;j<=n;j++){if(dist[i][j]==INF)continue;cnt = max(cnt,dist[i][j]);}ans = min(cnt,ans);}cout<<ans<<endl;
}signed main(){slove();
}

4-Crystal Switches

https://atcoder.jp/contests/abc277/tasks/abc277_e

/*给你一张图:
如果边权是0,则代表开关关闭,不能通过
如果边权是1,代表开关打开,能通过对于每个结点,记录:1、结点编号
2、当前结点被反转
3、步数从起点开始bfs
遍历所有u能去的点,
如果边权是0:打开开关,加入状态: node = { v , 1 , step+1 }
如果边权是1:不管开关,加入状态: node = { v , 0 , step+1 }接下来对于v,如果图中所有边被反转:那么边权原来是1的,现在就是0所以还是要操作开关,node = { i , 0 , step+1 }
如果边权原来是0的,现在就是1所以不需要操作开关,node = { i , 1 , step+1 }*/#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define PII pair<int,int>
#define INF 1e18struct node{int u;int step;int opt;bool operator < (node b)const{return step>b.step;}
};struct gg{int v;int w; //边权
};const int N = 2e5+7;
vector<gg> g[N];//存图
vector<int> s(N); //哪些结点上面有开关
int n,m;int flag[N][2]; // 每个结点的每种状态只访问一次。
int dist[N]; //1到n的最短路void dijkstra(){for(int i=1;i<=n;i++)dist[i]=INF;dist[1]=0;priority_queue<node> q;node now;now.u = 1;now.opt=0;now.step=0;q.push(now);while(q.size()){int u = q.top().u;int step = q.top().step;int opt = q.top().opt;q.pop();if(flag[u][opt])continue;flag[u][opt]=1;if(u==n){cout<<step<<endl;return;}node nxt;for(auto i:g[u]){int v = i.v;int w = i.w;//第一种情况,当前图没被反转,且该边能通过if(opt==0 and w==1){nxt.step = step+w;nxt.u = v;nxt.opt = opt;q.push(nxt);}else if(opt==0 and w==0)//第二种情况,当前图没被反转,但该边不能通过{//检查这个点是否有开关if(s[u]==1){nxt.step = step +1;nxt.u = v;nxt.opt = 1;q.push(nxt);}// 如果此路不通,且u没有开关,那么爱莫能助}else if(opt==1 and w==1) //如果图被反转了一次,此时w=1 相当于不能通过{if(s[u]==1) //如果有开关,那么再反转一次全图{nxt.step = step+1;nxt.u = v;nxt.opt = 0;q.push(nxt);}}else if(opt==1 and w==0) //如果地图被反转1次,此时w=0,代表可以通过{nxt.step = step+1;nxt.u = v;nxt.opt = opt;q.push(nxt);}}}cout<<-1<<endl;}
void slove(){int k;cin>>n>>m>>k;for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;g[u].push_back(gg{v,w});g[v].push_back(gg{u,w});}for(int i=1;i<=k;i++){int t;cin>>t;s[t]=1;}dijkstra();}signed main(){slove();
}

5-Shortest Path Queries 2

https://atcoder.jp/contests/abc208/tasks/abc208_d

纯板子,呆题

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define PII pair<int,int>
#define INF 1e18const int N = 405;
int dist[N][N];void slove(){int n,m;cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){dist[i][j]=INF;}dist[i][i]=0;}for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;dist[u][v]=w;}int ans = 0;for(int k=1;k<=n;k++){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){dist[i][j] = min(dist[i][j] , dist[i][k] + dist[k][j]);if(dist[i][j]!=INF){ans += dist[i][j];}}}}cout<<ans<<endl;
}signed main(){slove();
}

6- Jumping Takahashi 2

https://atcoder.jp/contests/abc257/tasks/abc257_d

二分+bfs

/*题目的意思是:让我们选择一个起始的蹦床。能从这个蹦床去到所有的蹦床的最小跳跃高度。然后找到这些最小跳跃高度中最小的那一个。我们可以二分跳跃高度 s然后枚举每一个起点。判断,这个跳跃高度是否能跳到任意一个蹦床。现在,问题就是,如何写check函数?可以写一个bfs,求连通性。如果最终连通,那么这个s是ok的时间复杂度: O(n^2 * log(1e10))*/#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define PII pair<int,int>
#define INF 1e18struct node{int id;int x;int y;int p;
};const int N =201;
node a[N];int ans = INF; //答案
int n;
bool flag[201];bool check(int mid,int start){memset(flag,0,sizeof flag);queue<node> q;q.push(a[start]);flag[start]=1;while(q.size()){int x = q.front().x;int y = q.front().y;int p = q.front().p;q.pop();node nxt;for(int i=1;i<=n;i++){if(flag[i])continue;int xx = a[i].x;int yy = a[i].y;int dist = abs(x-xx)+abs(y-yy);if(mid*p>=dist){q.push(a[i]);flag[i]=1;}}}for(int i=1;i<=n;i++){if(flag[i]==0)return false;}return true;
}
void work(int start){//二分跳跃高度int l=1, r = 1e10;while(l<r){int mid = l+r>>1;if(check(mid,start)){r=mid;}else{l=mid+1;}}ans = min(ans,l);
}
void slove(){cin>>n;for(int i=1;i<=n;i++){cin>>a[i].x>>a[i].y>>a[i].p;a[i].id=i;}for(int i=1;i<=n;i++){work(i);}cout<<ans<<endl;
}signed main(){slove();
}

7-Skiing

https://atcoder.jp/contests/abc237/tasks/abc237_e

最长路的处理方法之一:1、所有边权都乘上-1,然后跑spfa
值得注意的是,此题的时间需要不超过 O(NM)2、跑不了spfa,只能跑dijkstra
此时必须要从边权的计算方式,题目含义等条件入手。
来消除负权边。(吃经验 or 思维)
/*重力势能只与初始状态和末尾状态有关。初始状态是h[1],末尾状态是h[i]重力势能的变化就是 初状态 - 末状态 = h[1] - h[i]但是,这题没有这么简单。如果你走上坡路,那么消耗的是同等高度走下坡路的两倍。如果你走下坡路,只要你这个点是中间状态,那么一律不需要管,因为下坡路的贡献最终都会被抵消,剩下h[1]-[i]所以得到一个结论:假如初始状态和末尾状态都确定了,那么我们要想让最终答案最大。我们就必须使得走的上坡路的总代价越小 (这里说的是绝对值)也就是走最短路。而由于下坡路是没有影响的,所以下坡路的边权为0上坡路的边权 为1倍的  abs(h[u]-h[v])*/#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define PII pair<int,int>
#define INF 1e18
const int N = 2e5+7;struct node{int v;int w;
};vector<node> g[N];int n,m;
int h[N];
int dist[N];
bool flag[N];
priority_queue<PII,vector<PII>,greater<PII>> q;void dijkstra(){for(int i=1;i<=n;i++)dist[i]=INF;dist[1]=0;q.push({0,1});while(q.size()){int u = q.top().second;q.pop();for(auto i:g[u]){int w = i.w;int v = i.v;if(dist[v]>dist[u]+w){dist[v]=dist[u]+w;q.push({dist[v],v});}}}
}
void slove(){cin>>n>>m;for(int i=1;i<=n;i++)cin>>h[i];for(int i=1;i<=m;i++){int u,v;cin>>u>>v;int w = h[v]-h[u];if(w<0){ // u > vg[u].push_back(node{v,0});g[v].push_back(node{u,-w});}else // u<v{g[u].push_back(node{v,w});g[v].push_back(node{u,0});}}dijkstra();int ans = -INF;for(int i=1;i<=n;i++){ans = max(ans, h[1]-h[i] - dist[i]);}cout<<ans<<endl;}signed main(){slove();
}

8-Wizard in Maze

https://atcoder.jp/contests/abc176/tasks/abc176_d

bfs模板题

打的太多了,所以直接贴个答案上去。

#include<iostream>
#include<cstring>
#include<deque>
using namespace std;int h, w, ch, cw, dh, dw, dis[1005][1005];
//dis[i][j]表示从(ch, cw)出发到达(i, j)所消耗跳跃魔法次数的最小值
char a[1005][1005];
int dx[4] = {0, 0, -1, 1};
int dy[4] = {-1, 1, 0, 0};struct node
{ //从(ch, cw)出发到达(x, y)所消耗跳跃魔法次数的最小值tint x, y, t;
};deque<node> q;void bfs()
{q.push_front(node{ch, cw, 0});dis[ch][cw] = 0;while(!q.empty()){int x = q.front().x, y = q.front().y, t = q.front().t;q.pop_front();//(x,y)普通移动能达到的子结点插入队首for(int i = 0; i <= 3; i++){int x_new = x + dx[i], y_new = y + dy[i];if(x_new < 1 || x_new > h || y_new < 1 || y_new > w) continue;if(a[x_new][y_new] == '#') continue;if(dis[x_new][y_new] <= dis[x][y]) continue;q.push_front(node{x_new, y_new, t});dis[x_new][y_new] = t;}//(x,y)跳跃魔法移动能达到的子结点插入队尾for(int x_new = x - 2; x_new <= x + 2; x_new++)for(int y_new = y - 2; y_new <= y + 2; y_new++){if(x_new < 1 || x_new > h || y_new < 1 || y_new > w) continue;if(a[x_new][y_new] == '#') continue;if(dis[x_new][y_new] <= dis[x][y] + 1) continue;q.push_back(node{x_new, y_new, t + 1});dis[x_new][y_new] = t + 1;}}
}int main()
{cin >> h >> w;cin >> ch >> cw;cin >> dh >> dw;for(int i = 1; i <= h; i++)for(int j = 1; j <= w; j++)cin >> a[i][j];memset(dis, 0x3f, sizeof(dis));bfs();if(dis[dh][dw] == 0x3f3f3f3f) cout << -1 << endl;else cout << dis[dh][dw] << endl;return 0;
}

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

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

相关文章

RN封装三角形组件(只支持上下箭头)

import React from react; import { View, StyleSheet } from react-native;const Triangle ({ direction, width, height, color }) > {// 根据方向选择三角形的样式const triangleStyle direction up? {borderTopWidth: 0,borderBottomWidth: height,borderLeftWidth: …

docker完美安装分布式任务调度平台XXL-JOB

分布式任务调度平台XXL-JOB 1、官方文档 自己看 https://www.xuxueli.com/xxl-job/#1.1%20%E6%A6%82%E8%BF%B0 2、使用docker部署 本人使用的腾讯云&#xff0c;安装docker暴露一下端口&#xff0c;就很舒服的安装这个服务了。 docker pull xuxueli/xxl-job-admin:2.4.03…

Harmony鸿蒙南向驱动开发-PIN接口使用

功能简介 PIN即管脚控制器&#xff0c;用于统一管理各SoC的管脚资源&#xff0c;对外提供管脚复用功能&#xff1a;包括管脚推拉方式、管脚推拉强度以及管脚功能。 PIN接口定义了操作PIN管脚的通用方法集合&#xff0c;包括&#xff1a; 获取/释放管脚描述句柄&#xff1a;传…

代码随想录算法训练营第三十七天|● 738.单调递增的数字 ● 968.监控二叉树

738.单调递增的数字 class Solution { public:int monotoneIncreasingDigits(int n) {string a to_string(n);int k 0;for (int i a.size() - 1; i > 0; i--) {if (a[i] < a[i - 1]) {k i;a[i-1]--;}}cout << k << endl;if (k ! 0){for (int i a.size…

c# Xml 和 Json 转换方法记录

c# xml 转 json 在C#中&#xff0c;可以使用下面几种方法将XML转换为JSON&#xff1a; 使用Newtonsoft.Json库&#xff1a; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using System.Xml;// 从XML字符串转换为JSON字符串 string …

安卓手机APP开发的媒体相关内容播放列表

安卓手机APP开发的媒体相关内容播放列表 目录 概述 修改播放列表 查询播放列表 重复模式 随机模式 设置一个定制的随机顺序 标识播放列表中的媒体项 把APP数据和播放列表媒体项关联起来

好玩的Unicode表情

Unicode表情符号是Unicode标准的一部分&#xff0c;适用于任何支持Unicode编码的语言和平台。Unicode是一种国际通用的字符编码标准&#xff0c;它涵盖了世界上几乎所有的文字、符号和表情符号&#xff0c;确保不同系统间的信息交换能够准确无误。 分类方式 表情符号&#xf…

如何保证数据库、缓存的双写一致?

文章目录 前言常见方案更新缓存的方案1. 先写缓存&#xff0c;再写数据库2. 先写数据库&#xff0c;再写缓存2.1. 写缓存失败2.2. 高并发问题2.3. 性能浪费 3. 先删缓存&#xff0c;再写数据库3.1. 高并发问题3.2. 缓存双删 4. 先写数据库&#xff0c;再删缓存5. 删除缓存失败怎…

单例模式a

为什么需要单例模式&#xff1f; 保证类的实例在全局只有一个&#xff0c;避免无效对象创建和销毁时的资源消耗。 在Java中一切都是对象&#xff0c;实例方法的调用需要通过对象&#xff0c;为了调用类中的方法而创建对象&#xff0c;方法调用完成之后对象也需要被GC回收&…

Stable Diffusion之Ubuntu下部署

1、安装conda环境 conda create -n webui python3.10.6 2、激活环境 每次使用都要激活 conda activate webui 注意开始位置的变换 关闭环境 conda deactivate webui 3、离线下载SD 代码 https://github.com/AUTOMATIC1111/stable-diffusion-webui https://github.com/Stabilit…

CentOS7.9.2009安装Kibana7.11.1

本文章使用CentOS7.9.2009服务器安装kibana7.11.1软件 1.服务器信息 [root@elasticsearch ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) [root@elasticsearch ~]# 2.kibana安装 2.1.创建kibana用户 创建kibana用户和组 命令: useradd kibana [r…

10个大型语言模型(LLM)常见面试问题和答案解析

今天我们来总结以下大型语言模型面试中常问的问题 1、哪种技术有助于减轻基于提示的学习中的偏见? A.微调 Fine-tuning B.数据增强 Data augmentation C.提示校准 Prompt calibration D.梯度裁剪 Gradient clipping 答案:C 提示校准包括调整提示&#xff0c;尽量减少产生…

SQL注入sqli_labs靶场第九、十题

第九题 ?id1 and 11 页面正常 ?id1 and 12 页面正常 ?id1 and 11 页面正常 ?id1 and 12 页面正常 输入任何信息&#xff0c;均显示相同页面&#xff0c;尝试延时注入判断 ?id1 and if(11,sleep(5),1)-- 页面迅速显示 ?id1 and if(11,sleep(5),1)-- 页面过了5秒显示 判断为…

http请求头导致了dial tcp:lookup xxxx on 10.43.0.10:53 no sunch host

事实证明人有的时候也不能太偷懒&#xff0c;太偷懒容易给自己埋坑。 问题的背景&#xff1a; web端调用服务A&#xff0c;服务A异步调用服务B。服务A有四个场景需要调用服务B&#xff0c;所以&#xff0c;服务A中封装了一个公用的方法&#xff0c;唯一的区别是&#xff0c;场…

IDEA 控制台中文乱码 4 种解决方案

前言 IntelliJ IDEA 如果不进行相关设置&#xff0c;可能会导致控制台中文乱码、配置文件中文乱码等问题&#xff0c;非常影响编码过程中进行问题追踪。本文总结了 IDEA 中常见的中文乱码解决方法&#xff0c;希望能够帮助到大家。 IDEA 中文乱码 解决方案 一、设置字体为支…

手机银行客户端框架之mPaaS介绍

移动开发平台&#xff08;Mobile PaaS&#xff0c;简称 mPaaS&#xff09;是源于支付宝 App 的移动开发平台&#xff0c;为移动开发、测试、运营及运维提供云到端的一站式解决方案&#xff0c;能有效降低技术门槛、减少研发成本、提升开发效率&#xff0c;协助企业快速搭建稳定…

H. GCD is Greater

H. GCD is Greater 题意 给定一个长度为 n n n的数组 a a a&#xff0c;先手选择 [ 2 , n − 2 ] [2,n-2] [2,n−2]个数并计算所选择数的gcd&#xff0c;后手选择剩下的数&#xff0c;并计算剩下所有的数按位与的结果&#xff0c;再加上给定的 x x x&#xff0c;如果先手的结果…

Docker Redis Debian服务器版

1.使用官方安装脚本自动安装docker 安装命令如下&#xff1a; curl -fsSL https://get.docker.com -o get-docker.shsudo sh get-docker.sh 如果安装提示 -bash sudo command not found 则需要 #update sudo apt-get update sudo apt-get install sudo再执行安装脚本1 安装…

c++中常用库函数

大小写转换 islower/isupper函数 char ch1 A; char ch2 b;//使用islower函数判断字符是否为小写字母 if(islower(ch1)){cout << ch1 << "is a lowercase letter." << end1; } else{cout << ch1 << "is not a lowercase lette…

上采样-Lanczos插值

Lanczos插值是一种高级的上采样方法&#xff0c;它在计算目标图像中每个像素的值时&#xff0c;利用了周围像素的信息&#xff0c;并通过Lanczos滤波器进行插值计算&#xff0c;以产生较为清晰的结果。下面通过图文并茂的方式详细描述Lanczos插值方法的实现过程。 现在我们想将…