最大流ISAP算法(邻接表)模板

const int maxn=201;  

const int maxm=201;

struct node

{

         int x,y,f,op,next;      //x起点,y终点,f权值,next是以x为起点的上一条边在g中的位置,op是反向边在g中的下标位置

}g[maxm*2];

//first[]存储的是以x为起点的最后一条边的在数组g中的下标

//sumd[]用于记录表示标号为i的顶点数有多少个,用于间隙优化

int first[maxn],now[maxn],sumd[maxn];    

int ncount;                                //代表结点的总数

int dis[maxn],fanhui[maxn],pre[maxn],tot; //dis[]用于记录距离标号,pre[i]记录i的前驱在g[]中的位置,tot记录边的总数

void add(int x,int y,int c)

{

    tot++;        //tot记录边的总数

   g[tot].x=x;

    g[tot].y=y;   

    g[tot].f=c;

    g[tot].op=tot+1;        //反向边在g中的下标位置

   g[tot].next=first[x];   //记录以x为起点的上一条边在g中的下标位置

   first[x]=tot;           //以x为起点的边的位置

   tot++;           

     //反向边

   g[tot].x=y;

     g[tot].y=x;

     g[tot].f=0;             //反向边的初始网络流为0

     g[tot].op=tot-1;

     g[tot].next=first[y];

     first[y]=tot;   

}

//ISAP算法

int maxflow(int src,int des)            

{

         int i,flow,t,j,tempmin;   //i,j用于标识结点,t用于标识结点在g中的位置

         bool flag;                //用于标识是否找到了允许路径

         int sumFlow;             

         memset(dis,0,sizeof(dis));             

         memset(sumd,0,sizeof(sumd));

         for(i=1;i<=ncount;i++)           //遍历所有的结点

                     now[i]=first[i];     

         sumd[0]=ncount;                 //标号为0的结点有ncount个

       sumFlow=0;                      //sumFlow记录最大流,初始化为0

         i=src;                          //i初始化为起点

      flow=10000000;

         while(dis[src]<ncount)

         {

                     fanhui[i]=flow;

                     flag=false;    

                     t=now[i];

                     while(t!=0)           //寻找允许路径

                     {

                                 j=g[t].y;

                                 if((g[t].f>0)&&(dis[j]+1==dis[i])) //允许弧 

                                 {

                                              flag=true;

                                              pre[j]=t;

                                              now[i]=t;

                                              if(g[t].f<flow)          //找到允许增量

                                                          flow=g[t].f;

                                              i=j;

                                              if(i==des)                 //找到了允许路径

                                              {

                                                          sumFlow+=flow;

                                                          while(i!=src)          //修改残余网络

                                                          {

                                                                      g[pre[i]].f-=flow;            //正向边

                                                                      g[g[pre[i]].op].f+=flow;      //反向边

                                                                      i=g[pre[i]].x;

                                                          }

                                                          flow=10000000;

                                              }

                                              break;

                                 }

                                 t=g[t].next;

                     }

                     if(flag)

                                 continue;

                     //没有找到允许路径

                     tempmin=ncount-1;

                     t=first[i];

                     while(t!=0)

                     {

                                 if((g[t].f>0)&&(dis[g[t].y]<tempmin))

                                 {

                                              tempmin=dis[g[t].y];

                                              now[i]=t;

                                 }

                                 t=g[t].next;

                     }

                     sumd[dis[i]]--;

                     if(sumd[dis[i]]==0) break;           //间隙优化

                     dis[i]=tempmin+1;                          //此处别忘+1,因为d[i]=tempmin{d[j]+1|(i,j)在残留网络中}

                     sumd[dis[i]]++;

                     if(i!=src)

                     {

                                 i=g[pre[i]].x;

                                 flow=fanhui[i];

                     }

         }

         return sumFlow;

}

int main()

{

    int src,des;     //src是起点,des是终点

    memset(first,0,sizeof(first));       //初始化first

    tot = 0;                             //tot初始化为0

    ncount = n;        //初始化ncount为结点总数

    for(i=0;i<N;++i)

    {

        cin>>x>>y>>c;

        add(x,y,c);

    }

    printf("%d\n",maxflow(src,des)); 

    return 0;

}

 

 

posted @ 2010-05-29 21:47  北海小龙  阅读(913)  评论(0编辑  收藏  举报