网络流模板

//邻接矩阵

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int inf=(1<<30);
const int point_num=300;
int cap[point_num][point_num],dist[point_num],gap[point_num];//初始化见main里面
int s0,t0,n;//源,汇和建图后点数(0-n-1)
int find_path(int p,int limit=0x3f3f3f3f)
{
    if(p==t0)   return limit;
    for(int i=0;i<n;i++)
    if(dist[p]==dist[i]+1  &&  cap[p][i]>0)
    {
       int t=find_path(i,min(cap[p][i],limit));
       if(t<0)   return t;
       if(t>0)
       {
            cap[p][i]-=t;
            cap[i][p]+=t;
            return t;
       }
    }
    int label=n;
    for(int i=0;i<n;i++)  if(cap[p][i]>0)  label=min(label,dist[i]+1);
    if(--gap[dist[p]]==0  ||  dist[s0]>=n )   return -1;
    ++gap[dist[p]=label];
    return 0;
}
int sap()
{
    //初始化s,t
    s0=0,t0=n-1;
    int t=0,maxflow=0;
    gap[0]=n;
    while((t=find_path(s0))>=0) maxflow+=t;
    return maxflow;
}
int pig[1100];
int vis[1100];
int main()
{
    int m;
    while(scanf("%d%d",&m,&n)==2)
    {
        //初始化
        memset(cap,0,sizeof(cap));
        memset(dist,0,sizeof(dist));
        memset(gap,0,sizeof(gap));
        //初始化cap 重新赋值n
        printf("%d\n",sap());
    }
    return 0;
}

 

邻接表  较慢

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int inf=(1<<28);
using namespace std;
#define maxn 500000
struct edge
{
    int u,v,next,f,pre;
}e[2*maxn];
int num,rnum;
int head[maxn],rhead[maxn];
int d[maxn];
int numb[maxn];
int start[maxn];
int n,m;//见图后的点数(1->n)和原图边数
int p[maxn];
int source,sink;
//要初始化source 和 sink,重定义n
void Init()
{
    memset(head,-1,sizeof(head));
    memset(rhead,-1,sizeof(rhead));
    memset(p,-1,sizeof(p));
    num=0;
    return ;
}
void BFS()
{
    int i,j;
    for(i=1;i<=n;i++)
    {
        d[i]=n;
        numb[i]=0;
    }
    int Q[maxn],head(0),tail(0);
    d[sink]=0;
    numb[0]=1;
    Q[++tail]=sink;
    while(head<tail)
    {
        i=Q[++head];
        for(j=rhead[i];j!=-1;j=e[j].pre)
        {
            if(e[j].f==0||d[e[j].u]<n)
                continue;
            d[e[j].u]=d[i]+1;
            numb[d[e[j].u]]++;
            Q[++tail]=e[j].u;
        }
    }
    return ;
}
int Augment()
{
    int i;
    int tmp=inf;
    for(i=p[sink];i!=-1;i=p[e[i].u])
    {
        if(tmp>e[i].f)
            tmp=e[i].f;
    }
    for(i=p[sink];i!=-1;i=p[e[i].u])
    {
        e[i].f-=tmp;
        e[i^1].f+=tmp;
    }
    return tmp;
}
int Retreat(int &i)
{
    int tmp,j,mind(n-1);
    for(j=head[i];j!=-1;j=e[j].next)
    {
        if(e[j].f>0&&d[e[j].v]<mind)
            mind=d[e[j].v];
    }
    tmp=d[i];
    d[i]=mind+1;
    numb[tmp]--;
    numb[d[i]]++;
    if(i!=source)
        i=e[p[i]].u;
    return numb[tmp];
}
int maxflow()
{
    int flow(0),i,j;
    BFS();
    for(i=1;i<=n;i++)
        start[i]=head[i];
    i=source;
    while(d[source]<n)
    {
        for(j=start[i];j!=-1;j=e[j].next)
            if(e[j].f>0&&d[i]==d[e[j].v]+1)
                break;
        if(j!=-1)
        {
            start[i]=j;
            p[e[j].v]=j;
            i=e[j].v;
            if(i==sink)
            {
                flow+=Augment();
                i=source;
            }
        }
        else
        {
            start[i]=head[i];
            if(Retreat(i)==0)
                break;
        }
    }
    return flow;
}
//a->b=c;
void addedge(int a,int b,int c)
{
    e[num].next=head[a];
    head[a]=num;
    e[num].pre=rhead[b];
    rhead[b]=num;
    e[num].f=c;
    e[num].u=a;
    e[num++].v=b;
    e[num].next=head[b];
    head[b]=num;
    e[num].pre=rhead[a];
    rhead[a]=num;
    e[num].u=b;
    e[num].v=a;
    e[num++].f=0;
    return ;
}
int main()
{

    //init(); 重新赋值sourc sink n
    return 0;
}

 

邻接表 较快

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1010;
const int M=50000;
const int inf=(1<<28);
int head[N];
struct Edge
{
    int v,next,w;
} edge[M];
int cnt,n,s,t;//n从0开始  0->n-1
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 pre[N],cur[N],dis[N],gap[N];
    int flow=0,aug=inf,u;
    bool flag;
    for(int i=0; i<n; i++)
    {
        cur[i]=head[i];
        gap[i]=dis[i]=0;
    }
    gap[s]=n;
    u=pre[s]=s;
    while(dis[s]<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<aug) aug=edge[j].w;
                pre[v]=u;
                u=v;
                if(u==t)
                {
                    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]<mindis)
            {
                mindis=dis[v];
                cur[u]=j;
            }
        }
        if((--gap[dis[u]])==0)
            break;
        gap[dis[u]=mindis+1]++;
        u=pre[u];
    }
    return flow;
}

//初始化  cnt=0;memset(head,-1,sizeof(head));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值