最大流ISAP模板

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值