最大流dinic总结模版

const int N=550;
const int M=300000;
const int inf=1<<30;
//******************************************//
struct Node
{
    int v,next;
    int val;
}edge[M];

int level[N];//顶点的层次
int head[N];
int que[N*100];//BFS中用于遍历的顶点,DFS求增广中记录边
int out[N];//DFS用于几乎定点的分支
int ind;

void init()
{
    ind=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int c)
{
    edge[ind].v=v; edge[ind].val=c;  edge[ind].next=head[u];  head[u]=ind++;
    edge[ind].v=u; edge[ind].val=0;  edge[ind].next=head[v];  head[v]=ind++;
}
int dinic(int n,int source,int sink)
{
    int ret=0;
    int h=0,r=0;
    while(1)//DFS
    {
        int i;
        memset(level,0,sizeof(level));
        level[source]=1;
        que[h=r=0]=source;
        while(h<=r)//BFS
        {
            int  t=que[h++];
            for(i=head[t];i!=-1;i=edge[i].next)
                {
                    if(edge[i].val&&level[edge[i].v]==0)
                        {
                          level[edge[i].v]=level[t]+1;
                          que[++r]=edge[i].v;
                        }
                }
        }

        if(level[sink]==0)break;//找不到汇点
        for(i=0;i<=n;++i)out[i]=head[i];

        int  top=-1;
        while(1)
        {
            if(top<0)
            {
                int cur=out[source];
                for(;cur!=-1;cur=edge[cur].next)
                {
                    if(edge[cur].val&&out[edge[cur].v]!=-1&&level[edge[cur].v]==2)
                        break;
                }
                if(cur>=0)
                {
                    que[++top]=cur;
                    out[source]=edge[cur].next;
                }
                else
                    break;
            }
            int  u=edge[que[top]].v;
            if(u==sink)//一条增广路
            {
                int  dd=inf;
                int  index=-1;
                for(i=0;i<=top;i++)
                {
                    if(dd>edge[que[i]].val)
                    {
                        dd=edge[que[i]].val;
                        index=i;
                    }
                }
                ret+=dd;
                for(i=0;i<=top;i++)
                {
                    edge[que[i]].val-=dd;
                    edge[que[i]^1].val+=dd;
                }
                for(i=0;i<=top;i++)
                {
                    if(edge[que[i]].val==0)
                    {
                        top=index-1;
                          break;
                    }
                }
            }
            else
            {
                int cur=out[u];
                for(;cur!=-1;cur=edge[cur].next)
                {
                    if(edge[cur].val&&out[edge[cur].v]!=-1&&level[u]+1==level[edge[cur].v])
                        break;
                }
                if(cur!=-1)
                {
                    que[++top]=cur;
                    out[u]=edge[cur].next;
                }
                else
                {
                    out[u]=-1;
                    top--;
                }
            }
        }
    }
    return ret;
}
//**************************************************//

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值