Dinic算法

网络流的经典算法,原理依旧遵循增广路定理,只是在Ford-Fulkson算法的基础上,每次增广前求出残量网络中每个点到源点的距离,确保每次流的都是最短路。

注意当前弧优化

//Dinic

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

#define rep(i,x,y) for (int i=x;i<=y;i++)
#define dep(i,y,x) for (int i=y;i>=x;i--)
#define read(x) scanf("%d",&x)

using namespace std;

const int maxn=200+23,INF=(1<<23);

struct Edge{
  int from,to,flow,cap;
  Edge(int x1,int x2,int x3,int x4):from(x1),to(x2),flow(x3),cap(x4) {}
};

int d[maxn],cur[maxn],n,m,x,y,c,M,s,t;
bool vis[maxn];

vector<Edge> E;
vector<int> G[maxn];

void addedge(int u,int v,int c)
{
 E.push_back(Edge(u,v,0,c));
 E.push_back(Edge(v,u,0,0));
 M=E.size();
 G[u].push_back(M-2);
 G[v].push_back(M-1);
}

bool BFS()
{
 memset(vis,0,sizeof(vis));
 queue<int> Q;
 vis[s]=1;
 Q.push(s);
 d[s]=0;
 while (!Q.empty())
 {
  int x=Q.front(),len=G[x].size();Q.pop();
  rep(i,0,len-1)
  {
   Edge& Eg=E[G[x][i]];
   if ((!vis[Eg.to]) && (Eg.cap>Eg.flow))
   {
    vis[Eg.to]=1;
    Q.push(Eg.to);
    d[Eg.to]=d[x]+1;
   }
  }
 }
 return vis[t];
}

int DFS(int k,int a)
{
 if ((k==t) || (a==0)) return a;

 int len=G[k].size(),flow=0,f;

 for (int& i=cur[k];i<len;i++)
 {
  Edge& Ed=E[G[k][i]];
  if ((d[k]+1)!=(d[Ed.to])) continue;

  f=DFS(Ed.to,min(a,Ed.cap-Ed.flow));

  if (f>0) 
  {
   flow+=f;
   Ed.flow+=f;
   E[G[k][i]^1].flow-=f;
   a-=f;
   if (a==0) break;
  }
 }

 return flow;
}

int Maxflow()
{
 int flow=0;
 while (BFS())
 {
  memset(cur,0,sizeof(cur));
  flow+=DFS(s,INF);
 }
 return flow;
}

int main()
{
 scanf("%d%d",&m,&n);
 rep(i,1,m)
 {
  scanf("%d%d%d",&x,&y,&c);
  addedge(x,y,c);
 }
 
 s=1;t=n;

 printf("%d\n",Maxflow());
 return 0;
}
posted @ 2016-03-11 19:25  Krew  阅读(181)  评论(0)    收藏  举报