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

网站管理后台源码关键词优化平台有哪些

网站管理后台源码,关键词优化平台有哪些,公司做网站费用和人员配备,ue4培训图论相关帖子 基本概念图的表示: 邻接矩阵和邻接表图的遍历: 深度优先与广度优先拓扑排序图的最短路径:Dijkstra算法和Bellman-Ford算法最小生成树二分图多源最短路径强连通分量欧拉回路和汉密尔顿回路网络流算法: Edmonds-Karp算法网络流算法: Dinic算法 环境要求 本文所用…

图论相关帖子

  • 基本概念
  • 图的表示: 邻接矩阵和邻接表
  • 图的遍历: 深度优先与广度优先
  • 拓扑排序
  • 图的最短路径:Dijkstra算法和Bellman-Ford算法
  • 最小生成树
  • 二分图
  • 多源最短路径
  • 强连通分量
  • 欧拉回路和汉密尔顿回路
  • 网络流算法: Edmonds-Karp算法
  • 网络流算法: Dinic算法

环境要求

本文所用样例在Windows 11以及Ubuntu 24.04上面编译通过.

  1. Windows: 使用[Visual Studio],
  2. Ubuntu: 使用 Clang 18.1.3. (Ubuntu 24.04 系统安装版本)
  3. GCC 无法编译直接本项目代码, 因为本文代码使用了 C++20 Module, 而 GCC 对此支持不完整.

intro

Dinic 算法是一种用于解决最大流问题的高效算法, 它基于 Ford-Fulkerson 方法, 并通过引入层次图(level graph)的概念来加速寻找增广路径的过程. 我们先从层次图的概念开始.

层次图(Level Graph)

层次图是一个特殊的网络, 它通过引入层次值来表示节点之间的距离. 层次值从源点开始, 按照广度优先搜索(BFS)的顺序进行更新, 直到所有节点都被更新.

构建层次图的过程主要是通过从源点开始进行一次广度优先搜索(BFS), 根据节点到源点的距离来为每个节点分配层次值(level). 以下是构建层次图的具体步骤:

构建层次图的步骤

  1. 初始化:

    • 设定源点的层次值为 0.
    • 创建一个队列, 并将源点加入队列中.
  2. 执行广度优先搜索(BFS):

    • 从队列中取出一个节点 u u u.
    • 对于 u u u 的所有邻接节点 v v v, 如果边 ( u , v ) (u, v) (u,v) 在残量图中仍有剩余容量(即该边未被完全利用), 并且 v v v 还未被访问过(或其层次值尚未确定), 则:
      • 设置 v v v 的层次值为 u u u 的层次值加 1, 表示 v v v u u u “远” 一个单位距离.
      • v v v 加入队列中, 以便后续处理 v v v 的邻接节点.
    • 如果到达汇点, 则停止搜索; 否则继续直到队列为空.
  3. 结束条件:

    • 当队列为空时, 说明已经遍历了所有可到达的节点, 并且为这些节点分配了层次值. 此时, 如果汇点没有被访问到(即它没有层次值), 意味着无法再找到从源点到汇点的任何路径, 算法可以终止.
    • 如果汇点有层次值, 则层次图构建完成, 可以进行下一步的深度优先搜索(DFS)以寻找增广路径.

层次图构建样例

  1. 初始化. 给定一个原始图, 右侧是它的层次图初始状态.

    Level Graph Init

  2. 从源点(0)开始出发, 第一层接触到13. 将边(0, 1),(0, 3)加入到层次图中.

    Level Graph 1

  3. 接下来从13开始, 第二层接触到24. 将边(1, 2),(3, 2),(3, 4)加入到层次图中.

    Level Graph 2

  4. 最后从24开始, 第三层接触到5, 将边(2,5), (4,5)加入到层次图中.
    Level Graph 3

  5. 由于5是汇点, 所以算法结束. 最后的结果如下:

    Level Graph 4

层次图的作用

  • 限制搜索范围: 层次图只包含那些按照一定顺序(即按层次值从小到大)排列的节点和边, 这使得在寻找增广路径时只需考虑特定的边集, 减少了不必要的搜索.
  • 加快增广路径的查找速度: 由于 DFS 仅沿着层次图中的边进行搜索, 这样可以在较短的时间内找到一条或多条增广路径, 从而提高整个算法的效率.

通过以上步骤, Dinic 算法能够有效地构建层次图, 并利用这个结构快速找到增广路径, 最终求解最大流问题. 这种方法不仅提高了算法的性能, 而且使其实现更加直观易懂.

Dinic 算法步骤

Dinic 算法步骤

  1. 构建层次图: 从源点开始进行广度优先搜索(BFS), 为每个节点分配一个层次值(level), 这个值表示该节点到源点的距离. 只有当流量可以通过一系列边从一个较低层次的节点流向较高层次的节点时, 这条路径才会被纳入层次图中.

  2. 寻找增广路径: 使用深度优先搜索(DFS)在层次图中寻找从源点到汇点的增广路径. 由于层次图的性质, DFS 可以更高效地找到这些路径.

  3. 更新残量图: 一旦找到了一条增广路径, 就沿着这条路径调整流量, 同时更新相应的残量图. 这包括增加正向边的流量并减少反向边的容量.

  4. 重复步骤: 重复上述步骤, 直到无法再找到从源点到汇点的增广路径为止.

Dinic 算法样例

  1. 初始化: 给定一个原始图如图左侧所示, 如果我们省去容量为 0 的边, 那么左侧图可以看做是一个残量图, 右侧是它的层次图初始状态.

    dinic init

  2. 利用 DFS 寻找一条增广路径, 我们找到的了一条, 如图所示. 它的容量为 8, 接着我们更新残量图, 得到如图右边所示的图. 注意: 此时 1 -> 2 的边容量为 0, 故而省去.

    dinit 1

  3. 我们继续从残量图获取层级图. 如下:

    dinic-2

  4. 继续寻找增广路径, 找到一条, 如图所示, 容量为 3. 它的容量为 3, 接着我们更新残量图, 得到如图右边所示的图. 注意: 此时 3 -> 4 的边容量为 0, 故而省去.

    dinic 3

  5. 我们继续从残量图获取层级图. 如下:

    dinic 4

  6. 继续寻找增广路径, 找到一条, 如图所示, 容量为 1. 接着我们更新残量图, 得到如图右边所示的图. 注意: 此时 3 -> 2 的边容量为 0, 故而省去.

    dinic 5

  7. 我们继续从残量图获取层级图. 如下:

    dinic 6

  8. 继续寻找增广路径, 找不到了, 所以算法结束.

特点和优势:

  • 时间复杂度: Dinic 算法的时间复杂度为 O ( V 2 E ) O(V^2 E) O(V2E), 其中 V V V 是顶点数, E E E 是边数. 对于稠密图, 其性能优于 Edmonds-Karp 算法.
  • 阻塞流: Dinic 算法每次迭代都会尝试在当前层次图中找到一个"阻塞流", 即无法再在这个层次图中找到任何增广路径. 这种策略使得算法效率更高.
  • 应用广泛: 除了用于计算最大流之外, Dinic 算法还常用于解决二分图匹配等问题.

C++ 代码实现

class Dinic {public:explicit Dinic(const AdjList& graph): graph_(graph), residual_graph_(graph.V(), true, true) {BuildResidualGraph();}int MaxFlow(int src, int dst) {int max_flow = 0;while (true) {auto level = BuildLevelGraph(src);auto path = FindArgumentPath(level, src, dst);fmt::println("current path: {}", fmt::join(path, ", "));if (path.empty()) {break;}auto it = std::min_element(path.begin(), path.end(),[](const auto& lhs, const auto& rhs) {return std::get<2>(lhs) < std::get<2>(rhs);});int flow = std::get<2>(*it);if (flow <= 0) {break;}max_flow += flow;for (auto& [u, v, w] : path) {residual_graph_.UpdateWeight(u, v, -flow);residual_graph_.UpdateWeight(v, u, flow);}}return max_flow;}void BuildResidualGraph() {for (Vertex u = 0; u < graph_.V(); u++) {for (Vertex v : graph_.Adj(u)) {residual_graph_.AddEdge(u, v, graph_.GetWeight(u, v));residual_graph_.AddEdge(v, u, 0);}}}AdjList BuildLevelGraph(unsigned src) {AdjList g(graph_.V(), true, true);std::queue<unsigned> q;q.push(src);while (!q.empty()) {auto u = q.front();q.pop();for (auto v : residual_graph_.Adj(u)) {int w = residual_graph_.GetWeight(u, v);if (w <= 0 || g.HasEdge(u, v)) {continue;}g.AddEdge(u, v, w);q.push(v);}}return g;}std::vector<WeightedEdge> FindArgumentPath(const AdjList& graph, unsigned src,unsigned dst) {std::vector<unsigned> parent(graph.V(), UINT_MAX);std::vector<bool> visited(graph.V(), false);std::queue<unsigned> q;q.push(src);while (!q.empty()) {auto curr = q.front();q.pop();if (curr == dst) break;if (visited[curr]) continue;visited[curr] = true;for (auto w : graph.Adj(curr)) {if (visited[w]) continue;if (graph.GetWeight(curr, w) <= 0) continue;parent[w] = curr;q.push(w);}}std::vector<WeightedEdge> path;if (parent[dst] == UINT_MAX) return path;int curr = dst;while (parent[curr] != src) {auto begin = parent[curr];auto end = curr;auto weight = graph.GetWeight(begin, end);path.emplace_back(begin, end, weight);curr = begin;}path.emplace_back(src, curr, graph.GetWeight(src, curr));std::reverse(path.begin(), path.end());return path;}private:const AdjList& graph_;AdjList residual_graph_;
};

代码源文件链接在此: Dinic.ixx

http://www.mnyf.cn/news/42589.html

相关文章:

  • 伍佰亿网站推广域名138查询网
  • pc端与手机端网站开发的区别做电商必备的几个软件
  • 怎么查网站是哪个公司做的天津seo诊断技术
  • 如何判断网站是响应式的还是百度seo查询
  • 网站怎么做微博链接公众号运营收费价格表
  • brandoo wordpress优化电池充电什么意思
  • 上海网站制作网站建设拼多多推广引流软件免费
  • 在线音乐网站开发百度大数据查询平台
  • 网站没有收录从哪开始做优化优化网站搜索排名
  • 北京教育学会网站建设痘痘该如何去除效果好
  • 中英文网站开发谷歌在线浏览入口
  • wordpress阿里云邮箱上海网站排名优化公司
  • 用网上的文章做网站行吗怎样在百度做广告宣传
  • 如何找专业的网站建设公司优化网站性能
  • 网络营销建设网站实训惠州网络推广
  • 欧美个人网站徐州seo代理计费
  • 室内装修设计软件免费seo软件资源
  • 游戏网站开发毕业设计中国最近新闻大事件
  • 如何做网站走查郑州网站推广
  • 谷歌优化教程seo优化要做什么
  • joomla 1.5 网站建设基础教程网站宣传的方法有哪些
  • java 手机网站建设谷歌官网
  • 餐饮营销型网站建设排名优化方法
  • 网站建设流程要多少钱如何自己建立一个网站
  • 网站建设发展方向有哪些百度软文推广怎么做
  • 做毕业网站的流程中国站长站
  • 广州口碑好的网站建设设计5g网络优化工程师
  • 网站设计排行榜好用搜索引擎排名
  • 网站和网站的app重庆公司网站seo
  • 旅游网站模板html十大免费b2b网站