[置顶] 网络流DINIC增广路算法介绍

         网络流DINIC增广路算法

         【算法讲解】:首先构图,将节点间的容量和流量记录下。接下来,构建层次图<用队列实现,先将1加入,每次取队头元素x,然后枚举与它有边连的点y,根据层次图性质,每次判断x到y是否有容量并且d[x]+1是否小于d[y],如果是就更新d[y]为d[x]+1,并将y加进队列,若队列中元素有M个,就说明建图完毕>,然后进行DINIC网络流算法,递归求增广路,只是更新的时候要判断是否初始点的d值+1等于到达点<此处就是DINIC算法对普通增广路算法的优化>

         【题目】:POJ1273与USACO 4.2.1

                <题解链接>:

                      USACO Training 4.2.1 Drainage Ditches 草地排水 题解与分析<网络流DINIC算法>                         

                      POJ 1273 Drainage Ditches 题解与分析<网络流DINIC>

         【代码】:(以USACO4.2.1为例)

/*
   ID:csyzcyj1
   PROG:ditch
   LANG:C++
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define MAX 201
#define IMAX 2147483647
struct LAKE{vector<int> link;};
LAKE a[MAX];
int N,M,map[MAX][MAX],ans=0,use;//map记录容量 
int d[MAX];//d记录层次 
bool build()//构建层次图 
{
      int q[MAX],tot=0;
      for(int i=0;i<=M+1;i++)
            d[i]=IMAX;
      q[++tot]=1;
      d[1]=0;
      for(int i=1;i<=tot;i++)
      {
            int now=q[i];
            for(int j=0;j<a[now].link.size();j++)
            {
                  int next=a[now].link[j];
                  if(map[now][next] && d[now]+1<d[next])
                  {
                        d[next]=d[now]+1;
                        q[++tot]=next;
                        if(tot==M)   return true;
                  }
            }
      }
      return false;
}
int DINIC(int now,int flow)//flow为当前容量最小值 
{
      int new1;
      if(flow==0)  return 0;//没有可用容量 
      if(now==M)   return flow;//如果到达了汇点 
      for(int i=0;i<a[now].link.size();i++)
      {
            int next=a[now].link[i];
            if(d[now]+1==d[next] && (new1=DINIC(next,min(flow,map[now][next]))))
            {
                  map[now][next]-=new1;
                  map[next][now]+=new1;//其反向弧加上正向弧减去的流量 
                  return new1;
            }
      }
      return 0;
}
int main()
{
      freopen("ditch.in","r",stdin);
	  freopen("ditch.out","w",stdout); 
	  memset(map,0,sizeof(map));
	  scanf("%d%d",&N,&M);
	  for(int i=1;i<=N;i++)
	  {
            int A,B,C;
            scanf("%d%d%d",&A,&B,&C);
            map[A][B]+=C;
            a[A].link.push_back(B);
            a[B].link.push_back(A);
      }
      
      while(build())
      {
            while(use=DINIC(1,IMAX))
            {
                  ans+=use;
            }
      }
      printf("%d\n",ans);
	  //system("pause");
      return 0;
}


 

转载注明出处:http://blog.csdn.net/u011400953

 

你可能感兴趣的:([置顶] 网络流DINIC增广路算法介绍)