最大流: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; 

}
發佈了45 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章