最大流问题
dinic算法
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
/* 维护一个残余网络,c[i]表示正向残余流, c[i^1]表示反向残余流*/
const int N = 210, M = N*N;
const int INF = 0x3f3f3f3f;
int h[N], ne[M], e[M], idx, c[M]; //c存储边的容量
int dis[N]; //记录层次图中每个点的层数
int n, m;
int S; //源点
int T; //汇点
void add(int a, int b, int w)
{
e[idx]=b; ne[idx]=h[a];
c[idx]=w; h[a]=idx++;
}
bool bfs()
{ //bfs在残量图上重新分层,如果汇点在层次图中,则返回true
queue<int> q;
for(int i=1;i <= n;i++) dis[i]=0; //置为0,表示还未分配层数
q.push(S); dis[S]=1; //源点赋层数为1
while(!q.empty()){
int u=q.front();
q.pop();
if(u==T) return true;
for(int i=h[u]; ~i; i=ne[i])
{
int j=e[i];
if(!dis[j] && c[i]>0 ) //可以分配
{ //未分配层数并且可分配(余量大于0)
dis[j]=dis[u]+1;
q.push(j);
}
}
}
return false;
}
int dfs(int u, int flow)
{ //dfs求当前节点到汇点的最大流(dinic可以一次求出,主要利用dfs的回溯)
if(u==T) return flow;
int res=0;
int _flow=0; //从u出发的点的最大流
for(int i=h[u]; ~i; i=ne[i])
{
int j=e[i];
if(c[i]>0 && dis[u]+1==dis[j]) //下一层次点
{
_flow=dfs(j, min(flow-res, c[i])); //不会超过前面点的最大流也不会超过边的余流量
res+=_flow;
c[i]-=_flow; //正向减去增广
c[i^1]+=_flow; //反向加上增广
}
}
return res;
}
int dinic()
{ //直到残量图不连通
int ans=0;
while(bfs())
{
ans+=dfs(S, INF);
}
return ans;
}
int main()
{
cin>>m>>n;
memset(h, -1, sizeof h);
S=1; T=n;
for(int i=0;i<m;i++){
int a, b, w;
scanf("%d%d%d",&a,&b,&w);
add(a,b,w);
add(b,a,0);
}
printf("%d\n",dinic());
return 0;
}

浙公网安备 33010602011771号