最大流:SAP+GAP模版

题目:POJ-1273最大流模板题
code1:链式前向星(1)
#include  
#include  
#include  
#define MAXN 205 
#define MAXM 410 
#define INT_MAX 0x7fffffff 
using namespace std; 
int n,m; 
struct node
{
    int c,next,to;
} edge[MAXM];
int cnt,head[MAXN]; 
void addedge(int from,int to,int c)//这里存的还是一条有向边 
{
   edge[cnt].to=to;
    edge[cnt].c=c;
    edge[cnt].next=head[from]; head[from]=cnt++;
    edge[cnt].to=from;
    edge[cnt].c=0;     edge[cnt].next=head[to];
    head[to]=cnt++;
}
int gap[MAXN],h[MAXN],curedges[MAXN],pre[MAXN]; 
int start,end; 
int SAP_GAP() 
{
start=1;
    end=n; 
  //gap;  h:距离标号数组;curedges:当前弧数组;pre前驱数组 
  int cur_flow,flow_ans=0,u,tmp,neck,i;// 初始化最大0
  memset(h,0,sizeof(h)); 
  memset(gap,0,sizeof(gap)); 
  memset(pre,-1,sizeof(pre)); 
  for(i=1; i<=n; i++)
        curedges[i]=head[i];//初始化当前弧为第一条邻接边 
  gap[0]=n;
    u=start; 
     while(h[start]<</span>n) 
     {   if(u==end) 
     {   cur_flow=INT_MAX; 
         for(i=start; i!=end; i=edge[curedges[i]].to) 
         {   if(cur_flow>edge[curedges[i]].c) 
             {   neck=i;
                    cur_flow=edge[curedges[i]].c;
                } 
          }       //增广成功,寻找瓶颈边 
         for(i=start; i!=end; i=edge[curedges[i]].to) 
         {  tmp=curedges[i]; 
            edge[tmp].c-=cur_flow;
                edge[tmp^1].c=cur_flow; 
         }           
         flow_ans+=cur_flow;
            u=neck;
               } 
     for(i=curedges[u]; i!=-1; i=edge[i].next)        
      if(edge[i].c&&h[u]==h[edge[i].to]+1)
                break;  //寻找可行弧 
     if(i!=-1)       //找到可行弧 
     {   curedges[u]=i;
            pre[edge[i].to]=u;
            u=edge[i].to;
        } 
     else            //未找到可行弧 
     {   gap[h[u]]--; 
         if(gap[h[u]]==0)   break;  //GAP优化 
         curedges[u]=head[u]; 
         for(tmp=n,i=head[u]; i!=-1; i=edge[i].next) 
              if(edge[i].c)
                    tmp=min(tmp,h[edge[i].to]); 
         h[u]=tmp+1; 
         ++gap[h[u]]; 
         if(u!=start) u=pre[u];
               } 
     } 
     return flow_ans;
} 
void init() 
{   int from,to,c;
    cnt=0;
        memset(head,-1,sizeof(head)); 
   for(int i=0; i<</span>m; i++) 
     scanf("%d%d%d",&from,&to,&c);
        addedge(from,to,c);
    }
} 
int main() 
{
    //freopen("in.txt","r",stdin);
    while(~scanf("%d%d",&m,&n)) 
   {  init(); 
      printf("%d\n",SAP_GAP());
        } 
     return 0; 
}

code2:链式前向星(2)
 
  
 
  
#include  
#include  
#include  
#define inf 0x7fffffff
using namespace std;
 
const int N=205; 
const int M=500;//边是双向存的(注意不是无向)要开正常的2倍大 
 
struct Edge
{
    int v,next,w;
} edge[M];
int head[N],cnt,n,m,s=1; 
int pre[N],cur[N],dis[N],gap[N]; 
void addedge(int u,int v,int w)//这里存的还是一条有向边 
{  edge[cnt].v=v;
    edge[cnt].w=w; 
   edge[cnt].next=head[u];
    head[u]=cnt++; 
   edge[cnt].v=u;
    edge[cnt].w=0; 
   edge[cnt].next=head[v];
    head[v]=cnt++; 
} 
int sap() 
{  int flow=0,aug=inf,u;
    bool flag; 
   memset(pre,-1,sizeof(pre));
    memset(dis,0,sizeof(dis));    
   memset(gap,0,sizeof(gap)); 
   for(int i=1; i<=n; i++) 
       cur[i]=head[i];   
   gap[s]=n;   //初始化时全部处于gap[s] 
   u=pre[s]=s; 
   while(dis[s]<</span>n) 
   {   flag=0; 
       for(int &j=cur[u]; j!=-1; j=edge[j].next) 
       {  int v=edge[j].v; 
         if(edge[j].w>0&&dis[u]==dis[v]+1) 
       {  
                flag=1; 
            if(edge[j].w<</span>aug) aug=edge[j].w; 
                pre[v]=u;
                u=v; 
       if(u==n)    //如果到达end 
         {   flow+=aug; 
                 while(u!=s) 
                   {   u=pre[u]; 
                  edge[cur[u]].w-=aug; 
                      edge[cur[u]^1].w+=aug;//异或是找与其配对的边 
             } 
                    aug=inf; 
            } 
   break; 
        } 
   } 
   if(flag)                      //未找到可行边 
      continue; 
   int mindis=n; 
   for(int j=head[u]; j!=-1; j=edge[j].next) 
   {    int v=edge[j].v; 
 
  
        if(edge[j].w>0&&dis[v]<</span>mindis) 
        {  mindis=dis[v];
                cur[u]=j;
            } 
   } 
   if((--gap[dis[u]])==0)
            break; 
   dis[u]=mindis+1; 
   gap[dis[u]]++; 
   u=pre[u]; 
   } 
   return flow; 
} 
void init() 
{   int from,to,c;

    cnt=0; 
    memset(head,-1,sizeof(head)); 
    for(int i=0;i<</span>m;i++) 
    {  scanf("%d%d%d",&from,&to,&c);
        addedge(from,to,c);
    } 
} 
int main() 
{   while(~scanf("%d%d",&m,&n)) 
    {   
     init(); 
  printf("%d\n",sap()); 
    } 
    return 0;
}
 
  
code3:邻接矩阵
 
  
 
  
#include 
#include
#include 
#define M 205 
using namespace std; 
const int inf=~0U>>1; 
int n,nb,nc,m; 
int gap[M],flow[M][M],dist[M],cur[M];
int pre[M];
int source,end,s,t; 
int sap() 
{
   s=source;
    t=end; 
         memset(cur,0,sizeof(cur));
    memset(dist,0,sizeof(dist));  memset(gap,0,sizeof(gap)); 
     int u=pre[s]=s,maxflow=0,aug=inf; 
     gap[0]=n; 
     while(dist[s]<</span>n) 
     { 
    loop: 
            for(int v=cur[u];v<=n;v++) 
               {  if(flow[u][v]&&dist[u]==dist[v]+1) 
                       { 
                       cur[u]=v;
                aug=min(aug,flow[u][v]); 
                      pre[v]=u;
                u=v; 
                               if(v==t) 
                            {    maxflow+=aug; 
                                        for(u=pre[u];v!=s;v=u,u=pre[u]) 
                                         flow[u][v]-=aug,flow[v][u]+=aug; 
                                  aug=inf;
                                            } 
                                  goto loop; 
                        } 
           } 
           int mind=n; 
            for(int v=1;v<=n;v++) 
              if(flow[u][v]&&(mind>dist[v])) 
           {
   cur[u]=v;
            mind=dist[v];
            } 
                if((--gap[dist[u]])==0) break; 
         gap[dist[u]=mind+1]++; 
          u=pre[u];
            } 
      return maxflow; 
} 
void init() 
{        int from,to,c; 
      memset(flow,0,sizeof(flow));//没加这个 wa了4次 
    for(int i=0;i<</span>m;i++) 
       {
   scanf("%d%d%d",&from,&to,&c);
        flow[from][to]+=c;
    } 
       source=1;
    end=n; 
} 
int main() 
{
   int x,y,c; 
      while(~scanf("%d%d",&m,&n)) 
          { 
           init(); 
               printf("%d\n",sap()); 
      } 
   return 0; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值