[模板]网络最大流 & 最小费用最大流

我的作业部落有学习资料

 可学的知识点

Dinic 模板

#define rg register
#define _ 10001
#define INF 2147483647
#define min(x,y) (x)<(y)?(x):(y)
using namespace std;
int n,m,s,t,record[_],num_of_edges=-1,cur[_],team[10000001],depth[_];
struct pp
{
    int next,to,w;
}edge[(_<<4)+(_<<2)];
inline int read()
{
    rg int save=0,w=1;rg char q=getchar();
    while(q<'0'||q>'9'){if(q=='-')w=-1;q=getchar();}
    while(q>='0'&&q<='9')save=(save<<3)+(save<<1)+q-'0',q=getchar();
    return save*w;
}
inline void add(rg int from,rg int to,rg int ww)
{
    edge[++num_of_edges]=(pp){record[from],to,ww};
    record[from]=num_of_edges;
}
inline bool bfs()
{
    rg int head=0,tail=1;
    for(rg int i=1;i<=n;++i)depth[i]=0;//depth[]初值为-1,免得返回出发点
    depth[s]=1;
    team[1]=s;
    do
    {
        head++;
        rg int u=team[head];
        for(rg int j=record[u];j!=-1;j=edge[j].next)
        {
            rg int to=edge[j].to;
            if((!depth[to])&&(edge[j].w>0))
            {
                depth[to]=depth[u]+1;
                team[++tail]=to;
                if(to==t)return 1;
            }
        }
    }while(head<tail);
    return 0;
}
int dfs(rg int u,rg int flow)//找到每条路上的最小残余流量,因此需在回溯时更新每条边的流量
{
    if(u==t)return flow;
    for(rg int &j=cur[u]/*当前弧优化*/;j!=-1;j=edge[j].next)
    {
        rg int to=edge[j].to;
        if(depth[to]==depth[u]+1&&(edge[j].w>0))
        {
            rg int D=dfs(to,min(flow,edge[j].w));//到终点的过程中一直在取min
            if(D>0)
            {
                edge[j].w-=D,edge[j^1].w+=D;
                return D;//每次只找一条可流通路满上(这里就不管现实中物理的联通器原理了)
            }
            
        }
    }
    return 0;
}
inline int Dinic()
{
    rg int i,j,ans=0;
    while(bfs())
    {
        for(i=1;i<=n;++i)cur[i]=record[i];
        while(int now=dfs(s,INF))ans+=now;
    }
    return ans;
}
int main()
{
    n=read(),m=read(),s=read(),t=read();
    rg int i,j;
    for(i=1;i<=n;++i)record[i]=-1;
    for(i=1;i<=m;++i)
    {
        rg int x=read(),y=read(),ww=read();
        add(x,y,ww),add(y,x,0);
    }
    printf("%d\n",Dinic());
    return 0;
}

 最小费用最大流:

#define rg register
#define _ 5001
#define __ 50001
#define INF 2147483647
using namespace std;
int n,m,s,t,record[_],num_of_edges=1,pre[_],res_flow,res_cost,dis[_],team[__<<4];//以后num_of_edges都赋为 1 !!!
bool exist[_];
struct pp
{
    int next,to,w,cost;
}edge[__<<1];
inline int read()
{
    rg int save=0,w=1;rg char q=getchar();
    while(q<'0'||q>'9'){if(q=='-')w=-1;q=getchar();}
    while(q>='0'&&q<='9')save=(save<<3)+(save<<1)+q-'0',q=getchar();
    return w*save;
}
inline void add(rg int from,rg int to,rg int ww,rg int f)
{
    edge[++num_of_edges]=(pp){record[from],to,ww,f};
    record[from]=num_of_edges;
}
inline bool SPFA()
{
    rg int head=0,tail=1;
    for(rg int i=1;i<=n;++i)exist[i]=0,dis[i]=INF;
    dis[s]=0;
    team[1]=s;
    do
    {
        head++;
        rg int i=team[head];
        exist[i]=0;
        for(rg int j=record[i];j;j=edge[j].next)
        {
            rg int to=edge[j].to;
            if(edge[j].w>0&&dis[to]>dis[i]+edge[j].cost)
            {
                dis[to]=dis[i]+edge[j].cost;
                pre[to]=j;
                if(!exist[to])team[++tail]=to,exist[to]=1;
            }
        }
    }while(head<tail);
    return dis[t]!=INF;
}
inline void doit()
{
    while(SPFA())
    {
        rg int flow=INF;
        for(rg int i=pre[t];i;i=pre[edge[i^1].to])
            flow=min(flow,edge[i].w);
        res_flow+=flow;
        res_cost+=dis[t]*flow;
        for(rg int i=pre[t];i;i=pre[edge[i^1].to])
            edge[i].w-=flow,edge[i^1].w+=flow;
    }
    printf("%d %d\n",res_flow,res_cost);
}
int main()
{
    n=read(),m=read(),s=read(),t=read();
    rg int i,j;
    for(i=1;i<=m;++i)
    {
        rg int u=read(),v=read(),w=read(),f=read();
        add(u,v,w,f),add(v,u,0,-f);
    }
    doit();//实在不想用那个MCMF()
    return 0;
}

 

posted @ 2018-07-30 15:30  Cwen_oier  阅读(211)  评论(1编辑  收藏  举报