网络流常用算法

1.sap

递归版。

View Code
#include <iostream>
using namespace std;

#define MAXN 10000
struct Edge
{
  int v, next, val;
  Edge( ) { }
  Edge( int V, int N, int Val): v(V), next(N), val(Val) {}             
}edge[MAXN];

int head[MAXN],size, flow, visit, sum, N, M, ans;
int gap[MAXN], h[MAXN];

/*
sap算法核心:
1.dfs搜索增广路
2.标号  若存在v(i, j), 则h[i] = h[j] + 1
3.gap优化 若出现断层。。则结束 
4.更新,正向更新,反向相减 
*/
 
void init( )
{
  for( int i = 0; i < MAXN; i++)
  {
      head[i] = -1;        
       
  }     
  size = 0;
     
}


void AddEdge( int u, int v, int val)
{
   edge[size] = Edge(v, head[u], val);
   head[u]  = size++;
   
   edge[size] = Edge(u, head[v], 0);
   head[v] = size++;
     
}


int dfs( int x, int flow = 0x7f7f7f7f)
{
   if( x == N )
   {
      return flow;    
   }
   int v, u, high = N, f, tf = 0;
   for( v = head[x]; v != -1; v = edge[v].next )
   {
      u = edge[v].v;
      if( edge[v].val > 0 )
      {
        if( h[x] == h[u] + 1 && (f = dfs(u, min(flow - tf, edge[v].val))))
        {
          edge[v].val -= f;
          edge[v^1].val += f;
          tf += f;
          if( h[1] >= N || tf == flow)
            return tf;       
        }
        high = min(high, h[u]);
      }   
        
   }
   if( tf  == 0 )
   {
      gap[h[x]]--;
      if( gap[h[x]] == 0 )
         h[1] = N;
      h[x] = high + 1; 
      gap[h[x]]++;     
   }
   return tf;    
}

void solve( )
{
   gap[0] = N;
   memset(h, 0, sizeof(h));
   sum = 0;
   while( h[1] < N )
      sum += dfs( 1 );
   printf("Case %d: %d\n",++ans, sum);  
}


int main( )
{
   int a, b, c, T;
   ans = 0;
   scanf("%d",&T);
   while( T-- )
   {
     scanf("%d%d",&N, &M);
     init( );
     for( int i = 1; i <= M; i++)
     {
       scanf("%d%d%d",&a, &b, &c);
       AddEdge(a, b, c);
     }
     solve( );
   } 
   return 0; 
} 

 

2. sap非递归版

View Code
#include <iostream>
#include <queue>
using namespace std;

#define MAXN 10000
struct  Edge
{
 int v, next, val;
 Edge( ) { }
 Edge( int V, int N, int Val): v(V), next(N), val(Val) { }
}edge[MAXN];


int head[MAXN], cur[MAXN], gap[MAXN], h[MAXN], path[MAXN], size, N, M, ans;
queue<int>q;

void init( )
{
  for( int i = 0; i < MAXN; i++)
     head[i] = -1;
  size = 0;     
     
}

void AddEdge( int u, int v, int val)
{
  edge[size] = Edge(v, head[u],val);
  head[u] = size++;
  
  edge[size] = Edge(u, head[v], 0);
  head[v] = size++;     
     
}

void bfs(  )
{
   q.push( N );
   while( !q.empty() )
   {
      int x = q.front();
      q.pop( );
      for( int u = head[x]; u != -1; u = edge[u].next)
      {
           int v = edge[u].v;
           if( h[v] == 0 && edge[u^1].val >  0)
           {   
               gap[0]--;
               h[v] = h[u] + 1;
               gap[h[v]]++;
               q.push( v );
           } 
      }
          
   }  
     
}


void sap( )
{
   memset(h, 0, sizeof(h));
   memset(gap, 0, sizeof(gap));
   for( int i = 0; i < MAXN; i++)
   {
       cur[i] = head[i];
       path[i] = 0;
   }
   gap[0] = N;
   int u = 1, v, flow = 0x7f7f7f7f, high, sum = 0;
   path[u] = u = 1;
   while( h[1] < N )
   {
     int f = 0;
     for( int &x = cur[u]; x != -1; x = edge[x].next )
     {
        if( edge[x].val > 0 )
        {
             int v = edge[x].v;
             int w = edge[x].val;
             if( h[u] == h[v] + 1 )
             {
                 
                 path[v] = u;
                 u = v;
                 flow = min(flow,  edge[x].val);
                 f = 1;
                 if( v == N )
                 {   
                     sum += flow;
                     for( u = path[v] ; v != 1; v = u, u = path[u])
                     {
                          edge[cur[u]].val -= flow;
                          edge[cur[u]^1].val += flow;
                     }     
                     flow = 0x7f7f7f7f;              
                 }
                 break;
              }      
                     
        }
     }
     if( f )
         continue;
     high = N;
     for( int t = head[u]; t != -1; t = edge[t].next )
     {
         int w = edge[t].val;
         int v = edge[t].v;
         if( w > 0 )
         {
            if( h[v] < high )
            {
              high = h[v];
              cur[u] = t;
            }    
         }
     }
     gap[h[u]]--;
     if( gap[h[u]] == 0 )
         h[1] = N;
     h[u] = high + 1;
     gap[h[u]]++;
     u = path[u];       
   }     
   printf("Case %d: %d\n",ans++,sum);
}

int main( )
{
  int a,b,c,T;
  scanf("%d", &T);
  ans = 1;
  while(T--)
  {
     scanf("%d%d", &N, &M);
     init( );
     for( int i = 0; i < M; i++)
     {
        scanf("%d%d%d",&a, &b,&c);
        AddEdge(a,b,c);       
     }
     sap();
  }
  return 0;
}

 

3.dinic非递归版本

View Code
#include <iostream>
#include <queue>
using namespace std;

#define MAXN 10610
struct Edge
{
  int v, next, val;
  Edge( ) { }
  Edge(int V,int N, int Val): v(V), next(N), val(Val) { }
}edge[MAXN];

queue<int>q;
int head[MAXN], h[MAXN], size, N, M, ans, cur[MAXN];

int Q[106000];

void init( )
{
  for( int i = 0; i < MAXN; i++)
     head[i] = -1;
  size = 0;     
}

void AddEdge( int u, int v, int val)
{
   edge[size] = Edge(v, head[u], val);
   head[u] = size++;
   
   edge[size] = Edge(u, head[v], 0);
   head[v] = size++;    
}

int bfs( )
{ 
  memset( h, -1, sizeof(h));
  q.push( 1 );
  h[1] = 0;
  while( !q.empty())
  {
     int x = q.front();
     q.pop( );
     for( int e = head[x];  e != -1; e = edge[e].next)
     {
         int w = edge[e].val;
         int v = edge[e].v;
         if( w >  0 && h[v] == -1)
         {
            h[v] = h[x] + 1;    
            q.push( v );
         }     
          
     }
         
  }
  return h[N] != -1;    
}


int dfs( )
{
   int e, u, v, w, p, i, sum = 0, f = 0;
   for( int i = 0; i <= N + 100; i++)
        cur[i] = head[i];
   p = 1;
   Q[p] = 1;
   while( p )
   {      
      int x = Q[p];
      if( x == N )
      {
         int flow = 0x7fffffff;
         for( i = 1; i < p; i++)
         {
            x = Q[i];
            e = cur[x];
            if( edge[e].val < flow )
                flow = edge[e].val;
         }
         int mid;
         for( i = 1; i < p; i++)
         {
            x = Q[i];
            e = cur[x];
            if( edge[e].val == flow )
               mid = i;
            edge[e].val -= flow;
            edge[e^1].val += flow;        
         }
         p = mid;
         sum += flow;
         continue;   
      } 
      for(e = cur[x]; e != -1; e = edge[e].next)
      {
        v = edge[e].v;
        w = edge[e].val;
        if( h[v] == h[x] + 1 && w >  0 )
        {
           Q[++p] =  v;   
           break;     
        }
      }
      cur[x] = e;
      if( e == -1 ) { p--;  cur[Q[p]] = edge[cur[Q[p]]].next; }  
   }
   return sum;
}


void solve( )
{
   int sum = 0;
   while( bfs( ) )
      sum += dfs( );
   printf("Case %d: %d\n",ans++,sum);
}

int main( )
{
  int a, b, c, T;
  scanf("%d",&T);
  ans = 1;
  while(T--)
  {
     scanf("%d%d",&N, &M);
     init( );
     for( int i = 1; i <= M; i++)
     {
       scanf("%d%d%d",&a, &b, &c);
       AddEdge(a, b, c);
     }
     solve( );          
  }  
  return 0;   
}

 

4.dinic递归版

View Code 
#include <iostream>
#include <queue>
using namespace std;

#define MAXN 1010
struct Edge
{
  int v, next, val;
  Edge( ) { }
  Edge(int V,int N, int Val): v(V), next(N), val(Val) { }
}edge[MAXN];
queue<int>q;

int head[MAXN], h[MAXN], size, N, M, flow, visit, ans;


void init( )
{
  for( int i = 0; i < MAXN; i++)
     head[i] = -1;
  size = 0;     
     
     
}

void AddEdge( int u, int v, int val)
{
   edge[size] = Edge(v, head[u], val);
   head[u] = size++;
   
   edge[size] = Edge(u, head[v], 0);
   head[v] = size++;    
}

int bfs( )
{ 
  memset( h, -1, sizeof(h));
  q.push( N );
  h[N] = 0;
  while( !q.empty())
  {
     int x = q.front();
     q.pop( );
     for( int e = head[x];  e != -1; e = edge[e].next)
     {
         int w = edge[e^1].val;
         int v = edge[e].v;
         if( w >  0 && h[v] == -1)
         { 
            //printf("x = %d v = %d w = %d\n", x, v, w);
            h[v] = h[x] + 1;    
            q.push( v );
         }     
          
     }
         
  }
  return h[1] != -1;    
}


int dfs(int x, int flow = 0x7f7f7f7f)
{
   if( x == N  )
   {
      return flow;
   }
   int e, tf = 0, f;
   for(e = head[x]; e != -1; e = edge[e].next)
   {
       int v = edge[e].v;
       int w = edge[e].val;
       if( h[x] == h[v] + 1 && w >  0 && (f = dfs(v, min(flow - tf, w))) )
       {
             
           edge[e].val -= f;   
           edge[e^1].val += f; 
           tf += f;
       }     
        
   } 
   if( tf == 0)
       h[x] = -1;
   return tf;
}


void solve( )
{
   int sum = 0;
   while( bfs( ) )
      sum += dfs(1);
   printf("Case %d: %d\n",ans++,sum);
}

int main( )
{
  int a, b, c, T;
  scanf("%d",&T);
  ans = 1;
  while(T--)
  {
     scanf("%d%d",&N, &M);
     init( );
     for( int i = 1; i <= M; i++)
     {
       scanf("%d%d%d",&a, &b, &c);
       AddEdge(a, b, c);
     }
     solve( );          
  }  
  return 0;   
}

转载于:https://www.cnblogs.com/tangcong/archive/2012/07/07/2580734.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值