再谈网络流

2024-05-10 12:18
文章标签 网络 再谈

本文主要是介绍再谈网络流,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里我已经讨论过网络流最大流基本算法,但是我们可以对这个算法进行时间上的优化。其中效果比较好的当属“最短增广路算法”,即每次都沿着最短增广路(即边数最少的增广路)进行增广。下面要介绍的算法均使用如下数据结构来表示一条弧。

struct Edge {int from, to,cap,flow;
};
这代表一条从from到to的容量为cap,流量为flow的弧。当且仅当flow<cap的时候,该弧存在于残量网络中。当cap=0的时候,意味着此边事反向弧,此时flow<=0。下面是插入弧的过程。注意,原图中的一条弧对应两个Edge结构体,一个是这条弧本身,另一个是它的反向弧。根据插入顺序不难看出,edge[0]和edge[1]互为反向弧。一般地,edge[x]与edge[x^1]互为反向弧。

void AddEdge (int from, int to, int cap){edges.push_back((Edge){from,to,cap,0});edges.push_back((Edge){from,to,0,0});m = edges.size();G[from].push_back(m-2);G[to].push_back(m-1);
}
这个数据结构兼顾了效率,代码清晰度和调试难度,它的最大的好处就是同时适用于稠密图和稀疏图,而且支持重边。我们很快就会看到,重边在最小费用流里是不能避免的。

Dinic算法。我们要介绍的第一种算法称为Dinic算法,从宏观上讲,该算法就是不停地用BFS构造层次图,然后用阻塞流来增广。“层次图”和阻塞流“是Dinic算法的关键词。什么叫层次图?假设在残量网络中,起点到结点u的距离为dist(u),我们把dist(u)看成结点u的”层次“。只保留每个点出发到下一层次的弧,得到的图就是层次图。(这里看不懂概念并不是很重要,可以通过下面的源代码理清程序思路)

struct Edge {int from, to, cap, flow;
}void AddEdge (int from, int to, int cap){edges.push_back((Edge){from,to,cap,0});edges.push_back((Edge){from,to,0,0});m = edges.size();G[from].push_back(m-2);G[to].push_back(m-1);
}int n,m,s,t; //结点数,边数(包括反向弧),源点编号,汇点编号
vector<Edge> edges; //边表 edge[e]和edge[e^1]互为反向弧
vector<int> G[maxn]; //邻接表,G[i][j]表示点i的第j条边在e数组中得序号
bool vis[maxn];   //BFS中使用
int d[maxn]  //从起点到i的距离
int cur[maxn]  //当前弧下表 (后面继续说明)bool BFS (){memset(vis,0,sizeof(vis));queue<int> q;q.push(s);d[s] = 0;vis[s] = 1;while(!q.empty()){int u = q.front(), q.pop();for(int i = 0; i < G[u].size(); i++){Edge& e = edges[G[u][i]];if(!vis[e.to] && e.cap > e.flow){vis[e.to] = 1;d[e.to] = d[u] + 1;q.push(e.to);}}}return vis[t];
}int DFS (int x, int a) //DFS过程除了当前结点x外,还需要传入一个表示目前为止所有弧的最小残量的a,当x为汇点,或者a=0时终止DFS过程,否则多路增广。这里还有一个重要的优化:保存每个结点x正在考虑的弧cur[x],以避免重复计算
{if(x==t || a==0) return a;int f, flow = 0;for(int& i = cur[x]; i < G[x].size(); i++){Edge& e = edges[G[x][i]];if(d[x]+1==d[e.to] && (f=DFS(e.to, min(a, e.cap-e.flow))) > 0){e.flow += f;edges[G[x][i]^1] -= f;flow += f;a -= f;if(a==0) brea;}}return flow;
}
//最后主过程,不停的用BFS构造分层网络,然后用DFS沿着阻塞流增广。
int MaxFlow (){int flow = 0;while(BFS()){memset(cur,0,sizeof(cur));flow += DFS(s,INF);}return flow;
}


这篇关于再谈网络流的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/976416

相关文章

【Altium】查找PCB上未连接的网络

【更多软件使用问题请点击亿道电子官方网站】 1、文档目标: PCB设计后期检查中找出没有连接的网络 应用场景:PCB设计后期,需要检查是否所有网络都已连接布线。虽然未连接的网络会有飞线显示,但是由于布线后期整板布线密度较高,虚连,断连的网络用肉眼难以轻易发现。用DRC检查也可以找出未连接的网络,如果PCB中DRC问题较多,查找起来就不是很方便。使用PCB Filter面板来达成目的相比DRC

通信系统网络架构_2.广域网网络架构

1.概述          通俗来讲,广域网是将分布于相比局域网络更广区域的计算机设备联接起来的网络。广域网由通信子网于资源子网组成。通信子网可以利用公用分组交换网、卫星通信网和无线分组交换网构建,将分布在不同地区的局域网或计算机系统互连起来,实现资源子网的共享。 2.网络组成          广域网属于多级网络,通常由骨干网、分布网、接入网组成。在网络规模较小时,可仅由骨干网和接入网组成

Toolbar+DrawerLayout使用详情结合网络各大神

最近也想搞下toolbar+drawerlayout的使用。结合网络上各大神的杰作,我把大部分的内容效果都完成了遍。现在记录下各个功能效果的实现以及一些细节注意点。 这图弹出两个菜单内容都是仿QQ界面的选项。左边一个是drawerlayout的弹窗。右边是toolbar的popup弹窗。 开始实现步骤详情: 1.创建toolbar布局跟drawerlayout布局 <?xml vers

使用 GoPhish 和 DigitalOcean 进行网络钓鱼

配置环境 数字海洋VPS 我创建的丢弃物被分配了一个 IP 地址68.183.113.176 让我们登录VPS并安装邮件传递代理: ssh root@68.183.113.176apt-get install postfix 后缀配置中的点变量到我们在 DigitalOcean 中分配的 IP:mynetworks nano /etc/postfix/main.cf

Linux网络编程之循环服务器

1.介绍 Linux网络循环服务器是指逐个处理客户端的连接,处理完一个连接后再处理下一个连接,是一个串行处理的方式,比较适合时间服务器,DHCP服务器.对于TCP服务器来说,主要阻塞在accept函数,等待客户端的连接。而对于UDP服务器来说,主要阻塞在recv函数. 2.循环服务器模型 TCP循环服务器: 算法如下:          socket(...);

Linux网络编程之简单并发服务器

1.概念 与前面介绍的循环服务器不同,并发服务器对服务请求并发处理。而循环服务器只能够一个一个的处理客户端的请求,显然效率很低. 并发服务器通过建立多个子进程来实现对请求的并发处理,但是由于不清楚请求客户端的数目,因此很难确定子进程的数目。因此可以动态增加子进程与事先分配的子进程相结合的方法来实现并发服务器。 2. 算法流程 (1)TCP简单并发服务器:     服务器子进程1:

Android 扇形网络控件 - 无网络视图(动画)

前言 一般在APP没有网络的情况下,我们都会用一个无网络的提示图标,在提示方面为了统一app的情况,我们一般使用简单的提示图标,偶尔只需要改变一下图标的颜色就一举两得,而不需要让PS来换一次颜色。当然app有图标特殊要求的就另当别论了。 效果图 当你第一眼看到这样的图,二话不说直接让UI给你切一张图标来的快对吧,我其实开始也是这么想的,但是到了做的app越来越多的时候,你就会发现就算是用

poj 2391 Ombrophobic Bovines (网络流)

这是一道很经典的网络流的题目。首先我们考虑假如我们的时间为无穷大。我们吧每个点拆成2个点 i和i' .。虚拟源点s和汇点t。对于每个点建边(s,i, a[i])  (i‘,t,ib[i]) 。 其中a[i]为给点有多少牛,b[i]为容量。i和j连通 建边 (i,j',inf);如果最大流==所有牛的个数,就可能装下所有的牛。那么现在我们考虑时间。假设最大时间为T.那么如果i到j的的最短时间>T

加载网络图片显示大图

1.将图片的uri列表和下标传给ImagePagerActivity public void imageBrower(int position, ArrayList<String> urls2) {Intent intent = new Intent(this, ImagePagerActivity.class); intent.putExtra(ImagePagerActivity

ESP32使用按键配网并通过LED指示网络状态

前言 上面我们已经可以通过 ESPTOUCH 和 Airkiss 给模块配网,并且存储在 nvs 中,重启后仍然可以联网,只是这样仍然不能满足我们实际的应用,这次我们增加按键作为输入,LED作为输出,实现长按按键配网,并可以通过LED指示网络状态。 添加自己的组件 为了让程序结构更加清晰,所以我们在smart_config例程的基础上做了修改,在main文件夹里新建了main.c 、smar