最大流dinic

基本思路:在求图的最大流时,首先用bfs把图分层,分层时注意流量是否大于零,和该点是否已分层。每一次分层都需要重置level数组,如果分层后,终点没有被分层,说明没有增广路了,,之后用dfs进行增广路搜索,如果流量不为零, 并且该节点到下一个节点,正好为差为1,就在可以在搜索增广路,如果增广路搜索到的流量大于零,就要构建残余网络,就返回该流量,若找不到返回零。
   
   
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include <stack>
#include <string>
#include <set>
#include <map>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define MAXX 300
#define INF 0x7fffffff
struct node
{
int to, cal, rev;
};
using namespace std;
vector<node>g[MAXX];
int level[MAXX];
int m ,n;
int iter[MAXX];
 
void add(int fr, int to, int cal)
{
int pos = -1;
for (int i=0; i<g[fr].size(); i++)
if (g[fr][i].to == to)
{
pos = i;
break;
}
if (pos != -1)
g[fr][pos].cal += cal;
else
{
g[fr].push_back((node){to, cal, g[to].size()});
g[to].push_back((node){fr, 0, g[fr].size()-1});
return ;
}
}
 
void bfs()
{
queue<int>q;
memset(level, -1, sizeof(level));
level[1] = 0;
q.push(1);
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i=0; i<g[u].size(); i++)
{
node &e = g[u][i];
if (e.cal > 0 && level[e.to] < 0)
{
level[e.to] = level[u]+1;
q.push(e.to);
}
}
}
while (!q.empty())
q.pop();
}
 
int dfs(int v, int f)
{
if (v == n)
return f;
for (int &i=iter[v]; i<g[v].size(); i++)
{
node &e = g[v][i];
if (e.cal>0 && level[e.to] == level[v]+1)
{
int d = dfs(e.to, min(f, e.cal)); //继续寻找增广路的最大流量
if (d>0)
{
e.cal -= d;
g[e.to][e.rev].cal += d; //更新边的流量。
return d;
}
}
}
return 0;
}
 
int max_flow(int s)
{
int flow = 0;
while (1)
{
bfs();
if (level[n] <= 0)
return flow;
int f;
memset(iter, 0, sizeof(iter));
while ((f = dfs(s, INF)) > 0) //搜索增广路的最小流量。
flow += f;
}
}
 
int main()
{
while (scanf("%d%d",&m, &n)!=EOF)
{
while (m--)
{
int fr, to, cal;
scanf("%d%d%d", &fr, &to, &cal);
add(fr, to, cal);
}
printf("%d\n", max_flow(1));
for (int i=1; i<=n; i++)
g[i].clear();
}
return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值