首页 > 编程语言 >disjkstra算法

disjkstra算法

时间:2022-11-23 13:55:53浏览次数:56  
标签:disjkstra ver int vertex 算法 cost que dis

图的两种表示方式

  1. 邻接矩阵

优点:方便查找,方便操作
缺点:需要空间过大

#define MAX_N 1000
#define ufr(i, x, y) for (int i = x; i <= y; ++i)
#define lfr(i, x, y) for (int i = x; i >= y; --i)
int G[MAX_N];
signed main(){
  cin >> n;
  ufr(i,1,n){
    int from,to,cost;
    cin >> from >> to >> cost;
    G[from][to]=cost;
  }
  return 0;
}
  1. 邻接链表

优点:存储空间小
缺点:查找指定边时间复杂度高

#define MAX_N 1000
#define ufr(i, x, y) for (int i = x; i <= y; ++i)
#define lfr(i, x, y) for (int i = x; i >= y; --i)
// 使用priority_queque时默认为最小堆
struct vertex {
  int from, to, cost;
  vertex(int from_, int to_, int cost_) : from(from_), to(to_), cost(cost_) {}
  vertex(int to_, int cost_) : to(to_), cost(cost_) {}
  vertex(int from_, int to_, bool token) : from(from_), to(to_) {}
  bool operator<(const vertex& v) const { return this->cost > v.cost; }
  bool operator==(const vertex& v) const {
    return this->from == v.from && this->to == v.to;
  }
};
int n,m;
ll dis[MAX_N];
vector<vertex> G[MAX_N];
signed main() {
  n = f.r(), m = f.r();
  ufr(i, 1, m) {
    from = f.r(), to = f.r(), cost = f.r();
    G[from].emplace_back(to, cost);
  }
  return 0;
}

算法使用

创建一个静态数组来存储源节点到其余结点的权值ll dis[MAX_N];
首先将源结点到其本身的权值设置为0,其余设为正无穷,然后将其放入一个小根堆构成的优先队列中

  fill(goto(dis, n), 2147483647);
  dis[s] = 0;
  priority_queue<vertex> que;
  que.emplace(s, dis[s]);

然后开始循环当\(que\)为空时结束循环,每次循环从\(que\)中取出距离到达源点距离最小的权值结点,首先进行判断,因为后面的操作都是增加操作,所有如果当前到达源点的权值小于本点,直接\(continue\)。然后遍历该结点,依次放入比现在到达源点的权值小的结点和其权值

  while (!que.empty()) {
    vertex v = que.top();
    que.pop();
    if (dis[v.to] < v.cost) continue;
    for (const vertex& ver : G[v.to]) {
      if (dis[ver.to] > v.cost + ver.cost) {
        dis[ver.to] = v.cost + ver.cost;
        que.emplace(ver.to, dis[ver.to]);
      }
    }
  }

最后遍历输出一下就行了

模板题目

click

#include <bits/stdc++.h>
#define _i i << 1
#define __i i << 1 | 1
#define cl tree[i].l
#define cr tree[i].r
#define mod(x) ((x) % MOD)
#define lowbit(x) (x & -x)
#define g1(x) get<0>(x)
#define g2(x) get<1>(x)
#define g3(x) get<2>(x)
#define ufr(i, x, y) for (int i = x; i <= y; ++i)
#define lfr(i, x, y) for (int i = x; i >= y; --i)
#define all(x) x.begin(), x.end()
#define goto(x, y) x + 1, x + y + 1
#define mm(x, y) memset(x, y, sizeof(x))
using namespace std;
using ld = long double;
using ll = long long;
using pp = pair<int, int>;

namespace Solution {
class fastio {
 public:
  template <class T = int>
  inline T r() noexcept {
    T x = 0, w = 1;
    char ch = 0;
    for (; !isdigit(ch); ch = getchar())
      if (ch == '-') w = -1;
    for (; isdigit(ch); ch = getchar()) x = (x << 3) + (x << 1) + (ch - '0');
    return x * w;
  }
  inline string rs() noexcept {
    string res;
    char ch = 0;
    for (ch = getchar(); ch == '\0' || ch == '\n' || ch == '\r'; ch = getchar())
      ;
    for (; ch != '\n' && ch != '\r'; ch = getchar()) res.append(1, ch);
    return res;
  }
  inline char rc() noexcept {
    char ch = getchar();
    for (; ch == '\0' || ch == '\n' || ch == '\r' || ch == ' '; ch = getchar())
      ;
    return ch;
  }

  template <class T = int>
  inline fastio& pt(T x) noexcept {
    static char sta[128];
    int top = 0;
    if (x < 0) x = -x, putchar('-');
    do {
      sta[top++] = x % 10, x /= 10;
    } while (x);
    while (top) putchar(sta[--top] + 48);
    return *this;
  }

  inline fastio& pts(const string s) noexcept {
    for (int i = 0; s[i] != '\0'; ++i) putchar(s[i]);
    return *this;
  }
  inline fastio& ptc(const char c) noexcept {
    putchar(c);
    return *this;
  }
  inline fastio& ln() noexcept {
    putchar('\n');
    return *this;
  }
} f;
// 使用priority_queque时默认为最小堆
struct vertex {
  int from, to, cost;
  vertex(int from_, int to_, int cost_) : from(from_), to(to_), cost(cost_) {}
  vertex(int to_, int cost_) : to(to_), cost(cost_) {}
  vertex(int from_, int to_, bool token) : from(from_), to(to_) {}
  bool operator<(const vertex& v) const { return this->cost > v.cost; }
  bool operator==(const vertex& v) const {
    return this->from == v.from && this->to == v.to;
  }
};

struct pp_hash {
  template <class T1, class T2>
  std::size_t operator()(const std::pair<T1, T2>& p) const {
    auto h1 = std::hash<T1>{}(g1(p));
    auto h2 = std::hash<T2>{}(g2(p));
    return h1 ^ h2;
  }
};
// less --> return __x < __y; || greater --> return __x > __y;
#define MAX_N 1001000
static constexpr ll MOD = 1e9 + 7;
static constexpr ll eps = -1e9;
static constexpr ll inf = 0x7fffffff;
int n, m, s, to, from, cost;
ll dis[MAX_N];
vector<vertex> G[MAX_N];
void solve() {
  priority_queue<vertex> que;
  que.emplace(s, dis[s]);
  while (!que.empty()) {
    vertex v = que.top();
    que.pop();
    if (dis[v.to] < v.cost) continue;
    for (const vertex& ver : G[v.to]) {
      if (dis[ver.to] > v.cost + ver.cost) {
        dis[ver.to] = v.cost + ver.cost;
        que.emplace(ver.to, dis[ver.to]);
      }
    }
  }
  ufr(i, 1, n) f.pt(dis[i]).ptc(' ');
}
}  // namespace Solution

signed main() {
  using namespace Solution;
  unordered_map<pp, int, pp_hash> mp;
  n = f.r(), m = f.r(), s = f.r();
  ufr(i, 1, m) {
    from = f.r(), to = f.r(), cost = f.r();
    G[from].emplace_back(to, cost);
  }
  fill(goto(dis, n), 2147483647);
  dis[s] = 0;
  solve();
  return 0;
}

标签:disjkstra,ver,int,vertex,算法,cost,que,dis
From: https://www.cnblogs.com/GuanStudy/p/16918044.html

相关文章

  • 6种常见排序算法实现
    importjava.util.Arrays;/***解法1:冒泡排序*解法2:插入排序*解法3:选择排序*解法4:归并排序*解法5:快速排序*解法6:堆排序*///leetcodesubmitregio......
  • node.js 实现国密算法
    node.js实现国密算法搭建node环境node.js下载官网下载:http://nodejs.cn/download/解压tar-xvfnode-v18.12.1-linux-x64.tar.xz配环境变量vi/etc/profile最......
  • 搜索引擎的那些事(32位MD5算法)
      对于学过密码学的同学来说,md5算法肯定不会很陌生。但是,对于我来说,md5是一个新的命题。那什么是md5呢?md5就是对已有的数据进行加密处理。当然,它还有别的用处,什么呢?比如......
  • 银行家算法(Java)
    系统安全状态安全状态指系统能按某种进程推进顺序(P1,P2,...,Pn)未每个进程Pi分配器所需资源,直至满足每个进程对资源的最大需求,使每个进程都可以顺利的完成,此时成(P1,P2,...,Pn)为......
  • 嵌入式操作系统内核原理和开发(固定内存分配算法)
       固定内存方式是最简单的方法,也是最容易想到的方法。所谓的固定内存,就是所有分配的内存单元都是一致的。不管你申请的内存大小是多少,它都有一个最小的内存。因此,你申......
  • 嵌入式操作系统内核原理和开发(内存分配算法)
       内存分配是操作系统必须面对的一个环节,除非这个系统本身不需要内存安排,所有业务可以通过全局数据和堆栈搞定。内存分配其实不困难,但是由内存引申出来的东西就比较复......
  • 嵌入式操作系统内核原理和开发(基于链表节点的内存分配算法)
      链接节点的内存分配方法,其实就是一种按需分配的内存分配方法。简单一点说,就是你需要多少内存,我就给你多少内存。当然,为了把分配的内存都连起来,我们还需要对分配节点进......
  • 嵌入式操作系统内核原理和开发(最快、最优、最差内存分配算法)
       前面我们说到了基于​​链表的内存分配​​算法。但是之前我们也说过,其实内存分配一般有三个原则,最快、最优和最差。最快比较好理解,就是寻找到合适的节点就立即分配......
  • 一步一步写算法(之链表排序)
       相比较线性表的排序而言,链表排序的内容稍微麻烦一点。一方面,你要考虑数据插入的步骤;另外一方面你也要对指针有所顾虑。要是有一步的内容错了,那么操作系统会马上给你......
  • 一步一步写算法(之字符串查找 中篇)
       昨天我们编写了简单的字符查找函数。虽然比较简单,但是也算能用。然而,经过我们仔细分析研究一下,这么一个简单的函数还是有改进的空间的。在什么地方改进呢?大家可以慢......