C/C++,图算法——Dinic最大流量算法

1 文本格式

// C++ implementation of Dinic's Algorithm 
#include<bits/stdc++.h> 
using namespace std;

// A structure to represent a edge between 
// two vertex 
struct Edge
{
    int v;  // Vertex v (or "to" vertex) 
    // of a directed edge u-v. "From" 
    // vertex u can be obtained using 
    // index in adjacent array. 

    int flow; // flow of data in edge 

    int C;    // capacity 

    int rev; // To store index of reverse 
    // edge in adjacency list so that 
    // we can quickly find it. 
};

// Residual Graph 
class Graph
{
    int V; // number of vertex 
    int* level; // stores level of a node 
    vector< Edge >* adj;
public:
    Graph(int V)
    {
        adj = new vector<Edge>[V];
        this->V = V;
        level = new int[V];
    }

    // add edge to the graph 
    void addEdge(int u, int v, int C)
    {
        // Forward edge : 0 flow and C capacity 
        Edge a{ v, 0, C, adj[v].size() };

        // Back edge : 0 flow and 0 capacity 
        Edge b{ u, 0, 0, adj[u].size() };

        adj[u].push_back(a);
        adj[v].push_back(b); // reverse edge 
    }

    bool BFS(int s, int t);
    int sendFlow(int s, int flow, int t, int ptr[]);
    int DinicMaxflow(int s, int t);
};

// Finds if more flow can be sent from s to t. 
// Also assigns levels to nodes. 
bool Graph::BFS(int s, int t)
{
    for (int i = 0; i < V; i++)
        level[i] = -1;

    level[s] = 0;  // Level of source vertex 

    // Create a queue, enqueue source vertex 
    // and mark source vertex as visited here 
    // level[] array works as visited array also. 
    list< int > q;
    q.push_back(s);

    vector<Edge>::iterator i;
    while (!q.empty())
    {
        int u = q.front();
        q.pop_front();
        for (i = adj[u].begin(); i != adj[u].end(); i++)
        {
            Edge& e = *i;
            if (level[e.v] < 0 && e.flow < e.C)
            {
                // Level of current vertex is, 
                // level of parent + 1 
                level[e.v] = level[u] + 1;

                q.push_back(e.v);
            }
        }
    }

    // IF we can not reach to the sink we 
    // return false else true 
    return level[t] < 0 ? false : true;
}

// A DFS based function to send flow after BFS has 
// figured out that there is a possible flow and 
// constructed levels. This function called multiple 
// times for a single call of BFS. 
// flow : Current flow send by parent function call 
// start[] : To keep track of next edge to be explored. 
//           start[i] stores  count of edges explored 
//           from i. 
//  u : Current vertex 
//  t : Sink 
int Graph::sendFlow(int u, int flow, int t, int start[])
{
    // Sink reached 
    if (u == t)
        return flow;

    // Traverse all adjacent edges one -by - one. 
    for (; start[u] < adj[u].size(); start[u]++)
    {
        // Pick next edge from adjacency list of u 
        Edge& e = adj[u][start[u]];

        if (level[e.v] == level[u] + 1 && e.flow < e.C)
        {
            // find minimum flow from u to t 
            int curr_flow = min(flow, e.C - e.flow);

            int temp_flow = sendFlow(e.v, curr_flow, t, start);

            // flow is greater than zero 
            if (temp_flow > 0)
            {
                // add flow  to current edge 
                e.flow += temp_flow;

                // subtract flow from reverse edge 
                // of current edge 
                adj[e.v][e.rev].flow -= temp_flow;
                return temp_flow;
            }
        }
    }

    return 0;
}

// Returns maximum flow in graph 
int Graph::DinicMaxflow(int s, int t)
{
    // Corner case 
    if (s == t)
        return -1;

    int total = 0;  // Initialize result 

    // Augment the flow while there is path 
    // from source to sink 
    while (BFS(s, t) == true)
    {
        // store how many edges are visited 
        // from V { 0 to V } 
        int* start = new int[V + 1];

        // while flow is not zero in graph from S to D 
        while (int flow = sendFlow(s, INT_MAX, t, start))

            // Add path flow to overall flow 
            total += flow;
    }

    // return maximum flow 
    return total;
}

// Driver program to test above functions 
int main()
{
    Graph g(6);
    g.addEdge(0, 1, 16);
    g.addEdge(0, 2, 13);
    g.addEdge(1, 2, 10);
    g.addEdge(1, 3, 12);
    g.addEdge(2, 1, 4);
    g.addEdge(2, 4, 14);
    g.addEdge(3, 2, 9);
    g.addEdge(3, 5, 20);
    g.addEdge(4, 3, 7);
    g.addEdge(4, 5, 4);

    // next exmp 
    /*g.addEdge(0, 1, 3 );
      g.addEdge(0, 2, 7 ) ;
      g.addEdge(1, 3, 9);
      g.addEdge(1, 4, 9 );
      g.addEdge(2, 1, 9 );
      g.addEdge(2, 4, 9);
      g.addEdge(2, 5, 4);
      g.addEdge(3, 5, 3);
      g.addEdge(4, 5, 7 );
      g.addEdge(0, 4, 10);

     // next exp
     g.addEdge(0, 1, 10);
     g.addEdge(0, 2, 10);
     g.addEdge(1, 3, 4 );
     g.addEdge(1, 4, 8 );
     g.addEdge(1, 2, 2 );
     g.addEdge(2, 4, 9 );
     g.addEdge(3, 5, 10 );
     g.addEdge(4, 3, 6 );
     g.addEdge(4, 5, 10 ); */

    cout << "Maximum flow " << g.DinicMaxflow(0, 5);
    return 0;
}
 

2 代码格式

// C++ implementation of Dinic's Algorithm 
#include<bits/stdc++.h> 
using namespace std;

// A structure to represent a edge between 
// two vertex 
struct Edge
{
	int v;  // Vertex v (or "to" vertex) 
	// of a directed edge u-v. "From" 
	// vertex u can be obtained using 
	// index in adjacent array. 

	int flow; // flow of data in edge 

	int C;    // capacity 

	int rev; // To store index of reverse 
	// edge in adjacency list so that 
	// we can quickly find it. 
};

// Residual Graph 
class Graph
{
	int V; // number of vertex 
	int* level; // stores level of a node 
	vector< Edge >* adj;
public:
	Graph(int V)
	{
		adj = new vector<Edge>[V];
		this->V = V;
		level = new int[V];
	}

	// add edge to the graph 
	void addEdge(int u, int v, int C)
	{
		// Forward edge : 0 flow and C capacity 
		Edge a{ v, 0, C, adj[v].size() };

		// Back edge : 0 flow and 0 capacity 
		Edge b{ u, 0, 0, adj[u].size() };

		adj[u].push_back(a);
		adj[v].push_back(b); // reverse edge 
	}

	bool BFS(int s, int t);
	int sendFlow(int s, int flow, int t, int ptr[]);
	int DinicMaxflow(int s, int t);
};

// Finds if more flow can be sent from s to t. 
// Also assigns levels to nodes. 
bool Graph::BFS(int s, int t)
{
	for (int i = 0; i < V; i++)
		level[i] = -1;

	level[s] = 0;  // Level of source vertex 

	// Create a queue, enqueue source vertex 
	// and mark source vertex as visited here 
	// level[] array works as visited array also. 
	list< int > q;
	q.push_back(s);

	vector<Edge>::iterator i;
	while (!q.empty())
	{
		int u = q.front();
		q.pop_front();
		for (i = adj[u].begin(); i != adj[u].end(); i++)
		{
			Edge& e = *i;
			if (level[e.v] < 0 && e.flow < e.C)
			{
				// Level of current vertex is, 
				// level of parent + 1 
				level[e.v] = level[u] + 1;

				q.push_back(e.v);
			}
		}
	}

	// IF we can not reach to the sink we 
	// return false else true 
	return level[t] < 0 ? false : true;
}

// A DFS based function to send flow after BFS has 
// figured out that there is a possible flow and 
// constructed levels. This function called multiple 
// times for a single call of BFS. 
// flow : Current flow send by parent function call 
// start[] : To keep track of next edge to be explored. 
//           start[i] stores  count of edges explored 
//           from i. 
//  u : Current vertex 
//  t : Sink 
int Graph::sendFlow(int u, int flow, int t, int start[])
{
	// Sink reached 
	if (u == t)
		return flow;

	// Traverse all adjacent edges one -by - one. 
	for (; start[u] < adj[u].size(); start[u]++)
	{
		// Pick next edge from adjacency list of u 
		Edge& e = adj[u][start[u]];

		if (level[e.v] == level[u] + 1 && e.flow < e.C)
		{
			// find minimum flow from u to t 
			int curr_flow = min(flow, e.C - e.flow);

			int temp_flow = sendFlow(e.v, curr_flow, t, start);

			// flow is greater than zero 
			if (temp_flow > 0)
			{
				// add flow  to current edge 
				e.flow += temp_flow;

				// subtract flow from reverse edge 
				// of current edge 
				adj[e.v][e.rev].flow -= temp_flow;
				return temp_flow;
			}
		}
	}

	return 0;
}

// Returns maximum flow in graph 
int Graph::DinicMaxflow(int s, int t)
{
	// Corner case 
	if (s == t)
		return -1;

	int total = 0;  // Initialize result 

	// Augment the flow while there is path 
	// from source to sink 
	while (BFS(s, t) == true)
	{
		// store how many edges are visited 
		// from V { 0 to V } 
		int* start = new int[V + 1];

		// while flow is not zero in graph from S to D 
		while (int flow = sendFlow(s, INT_MAX, t, start))

			// Add path flow to overall flow 
			total += flow;
	}

	// return maximum flow 
	return total;
}

// Driver program to test above functions 
int main()
{
	Graph g(6);
	g.addEdge(0, 1, 16);
	g.addEdge(0, 2, 13);
	g.addEdge(1, 2, 10);
	g.addEdge(1, 3, 12);
	g.addEdge(2, 1, 4);
	g.addEdge(2, 4, 14);
	g.addEdge(3, 2, 9);
	g.addEdge(3, 5, 20);
	g.addEdge(4, 3, 7);
	g.addEdge(4, 5, 4);

	// next exmp 
	/*g.addEdge(0, 1, 3 );
	  g.addEdge(0, 2, 7 ) ;
	  g.addEdge(1, 3, 9);
	  g.addEdge(1, 4, 9 );
	  g.addEdge(2, 1, 9 );
	  g.addEdge(2, 4, 9);
	  g.addEdge(2, 5, 4);
	  g.addEdge(3, 5, 3);
	  g.addEdge(4, 5, 7 );
	  g.addEdge(0, 4, 10);

	 // next exp
	 g.addEdge(0, 1, 10);
	 g.addEdge(0, 2, 10);
	 g.addEdge(1, 3, 4 );
	 g.addEdge(1, 4, 8 );
	 g.addEdge(1, 2, 2 );
	 g.addEdge(2, 4, 9 );
	 g.addEdge(3, 5, 10 );
	 g.addEdge(4, 3, 6 );
	 g.addEdge(4, 5, 10 ); */

	cout << "Maximum flow " << g.DinicMaxflow(0, 5);
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微服务实战系列之通信

前言 掰个指头数一数&#xff0c;博主的“微服务实战系列”从无到有&#xff0c;从零走到了十五。如果比作时钟&#xff0c;刚好走过了一刻度。 当初为什么要做这个系列&#xff0c;博主想了又想&#xff0c;私以为作为当下软件领域的几个“hot spot”之一&#xff0c;又乘着…

urllib 的 get 请求和 post 请求(二)

目录 一、爬取网页、图片视频 二、请求对象的定制 三、get请求的urlencode方法 四、post 请求英文翻译 一、爬取网页、图片视频 目标&#xff1a;下载数据 知识点&#xff1a;urllib.request.urlretrieve()下载 使用urllib下载网页、图片和视频 下载网页&#xff1a; #…

六、ZGC深度剖析

一、引言 对于Java 程序员来说&#xff0c;JVM 帮助我们做了很多事情。 JVM是虚拟机&#xff0c;能够识别字节码&#xff0c;就是class文件或者你打包的jar文件&#xff0c;运行在操作系统上。 JVM帮我们实现了跨平台&#xff0c;你只需要编译一次&#xff0c;就可以在不同的…

traj_dist 笔记 源代码解析(python部分)

1distance.py 1.1 METRIC_DIC 不同实现方法对应的函数路径 1.2 sspd 功能&#xff1a; 计算轨迹 traj_1 和 traj_2 之间的对称化段路径距离。 参数&#xff1a; traj_1&#xff1a;一个二维 numpy 数组&#xff0c;代表第一个轨迹。traj_2&#xff1a;一个二维 numpy 数组…

FreeRTOS的三处栈空间设置分析

1、汇编启动代码中设置栈 这个栈空间只有300字节&#xff0c;是用于汇编启动代码早期&#xff0c;以及调用C语言的main函数&#xff08;创建任务等&#xff09;在创建好任务&#xff0c;启动调取器后&#xff0c;这个栈空间就被抛弃掉&#xff0c;后续不会使用到等调度器开启后…

星际飞船大战

欢迎来到程序小院 星际飞船大战 玩法&#xff1a;滑动鼠标控制方向&#xff0c;点击鼠标左键射击&#xff0c;生命值100分&#xff0c;被敌船击中减去20&#xff0c; 5次生命复活机会&#xff0c;统计分数&#xff0c;快去星际飞船大战吧^^。开始游戏https://www.ormcc.com/pl…

Dijkstra求最短路 II(堆优化Dijkstra算法)

给定一个 n 个点 m 条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c;所有边权均为非负值。 请你求出 11 号点到 n 号点的最短距离&#xff0c;如果无法从 11 号点走到 n 号点&#xff0c;则输出 −1−1。 输入格式 第一行包含整数 n 和 m。 接下来 m 行每行包含…

鱼骨探矿的题解

原题描述&#xff1a; 题目描述&#xff1a; 众所周知&#xff0c;《我的世界》中一种非常流行的探矿方式就是鱼骨探矿。 我的世界的地图可以看作一个的正方形世界。 经过初步探测&#xff0c;在第 i 行&#xff0c;[li, ri] 区间内可能存在宝藏。为了探索效率&#xff0c;…

C# | 对比不同种类的锁

文章目录 C# 对比不同种类的锁异同点对比表使用方法lock语句Monitor类Mutex类Semaphore类ReaderWriterLock类 结语 C# 对比不同种类的锁 Hi&#xff0c;在C#编程中&#xff0c;想要保护共享资源&#xff0c;通常会用到各种类型的锁。今天我们就来一起看看C#中不同种类的锁&…

geolife 笔记:将所有轨迹放入一个DataFrame

单条轨迹的处理&#xff1a;geolife笔记&#xff1a;整理处理单条轨迹-CSDN博客 1 加载数据 import pandas as pd import numpy as np import datetime as dt import osdata_dir Geolife Trajectories 1.3/Data/ 1.1 列出所有文件夹 dirlist os.listdir(data_dir) dirlist…

基于Qt开发的闹钟

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);speecher new QTextToSpeech(this); }Widget::~Widget() {delete ui; }//定时器超时时&#xff0c;自动执行的…

Ubuntu22.04中用户的全名

概要&#xff1a; 用户的全名有别于用户名username username可以理解为账户名&#xff0c;或者说用户ID&#xff0c;用于确定身份&#xff0c;显然是必需的 用户全名则不是必需的&#xff0c;用户全名也叫做注释&#xff0c;是一种辅助信息&#xff0c;如果没有填写用户全名…

docker 资源控制

Docker的资源控制 对容器使用宿主机的资源进行限制&#xff0c;如cpu&#xff0c;内存&#xff0c;磁盘I/O Docker使用linux自带的功能cgroup(control grouos)是linux内核系统提供的一种可以限制&#xff0c;记录&#xff0c;隔离进程组使用的物理资源 Docker借助这个机制&…

MySQL执行流程_执行一条select语句,期间发生了什么

文章目录 执行一条select语句&#xff0c;期间发生了什么MySQL执行流程第一步&#xff1a;连接器第二步&#xff1a;查询缓存第三步&#xff1a;解析SQL第四步&#xff1a;执行SQL 执行一条select语句&#xff0c;期间发生了什么 MySQL执行流程 server层负责建立连接、分析和执…

Banana Pi BPI-R4 SBC/路由器推出,带双 10G SFP+ 端口+Wifi7支持

Banana Pi BPI-R4 wifi7路由器开发板 香蕉派 Banana Pi BPI-R4 根据著名Banana Pi品牌背后的公司Sinovoip提供的初步信息&#xff0c;他们即将推出的Banana Pi BPI-R4路由器板目前已经正式发售。与之前的 Banana Pi R3 板相比&#xff0c;这在规格上将有显着提升。这就是我们…

99基于matlab的小波分解和小波能量熵函数

基于matlab的小波分解和小波能量熵函数&#xff0c;通过GUI界面导入西储大学轴承故障数据&#xff0c;以可视化的图对结果进行展现。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。 99小波分解和小波能量熵函数 (xiaohongshu.com)https://www.xiaohongshu.co…

【离散数学】——期末刷题题库( 二元关系)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

eclipse的日志文件放在什么位置

eclipse的日志文件放在<workspace的目录>/.metadata目录下面&#xff0c;例如&#xff1a;

Java基础语法之访问修饰限定符

private 表示私有的&#xff0c;只能在同一个包中的同一个类使用 像这样就是在同一个包中的不同类用了private修饰的变量&#xff0c;这是非法的&#xff0c;那到底该如何给a赋值呢&#xff1f;可以在定义时就赋值&#xff0c;但这样的代码就没有可操作性&#xff0c;所以我们…

Nginx的location匹配和rewrite重写

一、location匹配 常用的正则表达式 ^ &#xff1a;匹配输入字符串的起始位置 $ &#xff1a;匹配输入字符串的结束位置 * &#xff1a;匹配前面的字符零次或多次。如“ol*”能匹配“o”及“ol”、“oll”&#xff1a;匹配前面的字符一次或多次。如“ol”能匹配“ol”及“oll…