当前位置: 首页 > news >正文

如果你总是写不对最短路(SPFA Dijkstra) ╥﹏╥...

有一个朋友总是因为最短路写不对而卡题……

SPFA

思路:

先把原点初始距离设好、入队并标记(即vis:是否在队列中),然后每次取队首节点并取消标记,将其邻接边松弛,若松弛成功则判断是否有负环(cnt >= 0),若暂时未发现负环则标记该节点并将其入队,直到发现负环或队列为空。

模板:

ver 1: 有重边,则用cnt记录入队次数而非松弛次数

点击查看代码
struct eg {int v, w;
};int dis[NM];
bool vis[NM];
int cnt[NM];bool spfa(vector<eg> g[], int s) {queue<int> q;memset(dis, 0x3f, (n+1)*sizeof(int));memset(cnt, 0, (n+1)*sizeof(int));memset(vis, 0, (n+1)*sizeof(bool));q.push(s);dis[s] = 0;vis[s] = true;cnt[s] ++;while (!q.empty()) {int u = q.front();q.pop();vis[u] = false;for (auto i : g[u]){int v = i.v, w = i.w;if (dis[v] > dis[u] + w){dis[v] = dis[u] + w;if (!vis[v]) {cnt[v]++;if (cnt[v] >= n) return false;vis[v] = true;q.push(v);}}}}return true;}

ver 2:与之相反,无重边则记录松弛次数:

点击查看代码
struct eg {int v, w;
};
vector<eg> g[NM];
int dis[NM], cnt[NM];
bool vis[NM];int n;
queue<int> q;
bool spfa(int s) {memset(dis, 0x3f, (n+1) * sizeof(int));q.push(s);vis[s] = true;dis[s] = 0;while (!q.empty()) {int u = q.front();q.pop();vis[u] = false;for (auto e : g[u]){int v = e.v, w = e.w;if (dis[v] > dis[u] + w) {dis[v] = dis[u] + w;cnt[v] = cnt[u] + 1;if (cnt[v] >= n) return false;if (!vis[v]) {vis[v] = true;q.push(v);}}}}return true;
}

注意:

  1. 视情况而定cnt的意义,具体见上
  2. memset不要忘记
  3. vis标记分别在原点入队、每一个点出队、入队时进行,不要少了
  4. 注意边权的数据类型

Dijkstra

思路:

先将原点初始距离设好,!!不要标记为确定最短路的集合(vis:是否已确定最短路)!!,加入优先队列(dis不为INF的待确定最短路的点集合)中。对于优先队列中的每一个点,取出dis最小的并判断它是否属于确定最短路的集合,若是则重新循环,若不是则标记为已经确定最短路,遍历该点的邻接边并松弛,若松弛成功则将链接的点加入优先队列中。

模板:

点击查看代码
struct ed {int v, w;
};struct nd {int dis, u;bool operator>(const nd& a) const { return dis > a.dis; }
};vector<ed> e[NM];
int dis[NM], vis[NM];
priority_queue<nd, vector<nd>, greater<nd>> q;void dij(int n, int s) {memset(dis, 0x3f, (n + 1) * sizeof(int));memset(vis, 0, (n + 1) * sizeof(int));dis[s] = 0;q.push({0, s});while (!q.empty()) {int u = q.top().u;q.pop();if (vis[u]) continue;vis[u] = 1;for (auto ed : e[u]) {int v = ed.v, w = ed.w;if (dis[v] > dis[u] + w) {dis[v] = dis[u] + w;q.push({dis[v], v});}}}
}

注意:

  1. 要有两个结构体:(1)用于邻接表存储的边eg (2)用于优先队列取出未确定最短路径集合中拥有最短路径的点
  2. 不要在判断vis前在循环外将源点或在循环内将其他点的vis设为true
  3. 记得q中存的是结构体

我要去给我朋友(不是我……吗qwq)讲题了,再见

http://www.sczhlp.com/news/18978/

相关文章:

  • 靠谱的全球电商网站seo每日一帖
  • 十大黄台软件app下载seo如何建立优化网站
  • 广州市民政局网站建设外贸推广平台有哪几个
  • 滁州网站建设梦天堂百度后台登陆入口
  • wordpress用户推广学seo优化
  • 张家界有没有做网站的公司西安最新消息今天
  • 国外html5网站建设研究现状企业关键词优化公司
  • 哪里可以买域名做网站网络推广搜索引擎
  • 不同程序建的网站风格企业网络推广方案策划书
  • 创建个人商城网站钟南山今天感染新冠了
  • 自助建网站平台seo是什么化学名称
  • 网站改版 报价国内打开google网页的方法
  • 免费网站营销计划百度用户服务中心客服电话
  • 政府网站建设情况调查今日头条郑州头条新闻
  • 中国交通建设集团有限公司待遇成都seo公司排名
  • 虎门做网站公司海南百度推广总代理
  • 园区二学一做网站关键词搜索工具
  • seo技术经理推广优化网站
  • 网站注册手机号安全吗潍坊网站建设
  • html链接网站模板seo学习网站
  • 厦门哪里有做网站seo关键词优化培训
  • 做电子商务的网站百度app下载最新版本
  • 兰州网站建设公司排名百度网盘帐号登录入口
  • 备案网站名称注意事项万网域名注册教程
  • 企业查询猫资深seo顾问
  • 8/19
  • 往届生做网站编辑北京搜索引擎优化seo专员
  • 免费做公益网站珠海seo排名收费
  • 医疗网站前置审批要多长时间故事式的软文广告例子
  • 到哪里建网站企业培训机构