[挂几个网络流板子]

[挂几个网络流板子]


最大流/最小割:Dinic

  • 代码
#include<bits/stdc++.h>
using namespace std;
const int N=10010,M=2e6+5;
const int INF=0x3f3f3f3f;
int n,m;
namespace graph{
    int hed[N],cnt=1,to[M],nxt[M],cap[M],flow[M];
    int S,T;
    int d[N];bool vis[N];
    void adde(int u,int v,int _cap){
        ++cnt;to[cnt]=v,cap[cnt]=_cap,nxt[cnt]=hed[u],flow[cnt]=0;hed[u]=cnt;
        ++cnt;to[cnt]=u,cap[cnt]=0,nxt[cnt]=hed[v],flow[cnt]=0;hed[v]=cnt;
    }
    queue<int>Q;
    bool bfs(){
        memset(vis,0,sizeof(vis));
        memset(d,0,sizeof(d));
        Q.push(S);vis[S]=1;
        while(!Q.empty()){
            int u=Q.front();Q.pop();
            for(int i=hed[u];i;i=nxt[i]){
                int v=to[i];
                if(!vis[v]&&cap[i]>flow[i]){
                    vis[v]=1,d[v]=d[u]+1;
                    Q.push(v);
                }
            }
        }
        return vis[T];
    }
    int dfs(int u,int F){
        if(u==T||!F)return F;
        int flownow=0;
        for(int i=hed[u];i;i=nxt[i]){
            int v=to[i];if(d[v]!=d[u]+1)continue;
            int f=dfs(v,min(F,cap[i]-flow[i]));
            flownow+=f;
            F-=f;
            flow[i]+=f,flow[i^1]-=f;
            if(!F)break;
        }
        if(!flownow)d[u]=0;
        return flownow;
    }
    int max_flow(){
        int fw=0;
        while(bfs())
            fw+=dfs(S,INF);
        return fw;
    }
}

int main(){
    using namespace graph;
    scanf("%d%d%d%d",&n,&m,&S,&T);
    for(int i=1;i<=m;++i){
        int u,v,w;scanf("%d%d%d",&u,&v,&w); 
        adde(u,v,w);
    }
    printf("%d\n",max_flow());
}

最小费用最大流

  • 代码
#include<bits/stdc++.h>
using namespace std;
const int N=1010,INF=0x3f3f3f3f,M=2000010;
int n,m;
namespace graph{
    int S,T,cnt=1,hed[N],to[M],nxt[M],cap[M],cost[M];
    inline void adde(int u,int v,int _fl,int _c){
        ++cnt;to[cnt]=v,nxt[cnt]=hed[u],cap[cnt]=_fl,cost[cnt]=_c;hed[u]=cnt;
        ++cnt;to[cnt]=u,nxt[cnt]=hed[v],cap[cnt]=0,cost[cnt]=-_c;hed[v]=cnt;
    }

    queue<int>Q;
    int d[N];bool vis[N];int incf[N];
    int pre[N];
    bool spfa(){
        for(int i=min(1,S);i<=max(n,T);i++)d[i]=INF;
        memset(vis,0,sizeof(vis));
        Q.push(S);d[S]=0;vis[S]=1;
        incf[S]=INF;
        while(!Q.empty()){
            int u=Q.front();vis[u]=false;Q.pop();
            for(int i=hed[u];i;i=nxt[i]){
                int v=to[i];
                if(!cap[i])continue;
                if(d[v]>d[u]+cost[i]){
                    d[v]=d[u]+cost[i];
                    incf[v]=min(incf[u],cap[i]);
                    pre[v]=i;
                    if(!vis[v])vis[v]=true,Q.push(v);
                }
            }
        }
        if(d[T]==INF)return false;
        return true;
    }
    int mincost,maxflow;
    void update(){
        int x=T;
        while(x!=S){
            int i=pre[x];
            cap[i]-=incf[T];
            cap[i^1]+=incf[T];
            x=to[i^1];
        }
        maxflow+=incf[T];
        mincost+=d[T]*incf[T];
    }

    void mincost_maxflow(){
        while(spfa())update();
        cout<<maxflow<<" "<<mincost<<endl;
    }
}

int main()
{
    using namespace graph;
    scanf("%d%d%d%d",&n,&m,&S,&T);
    for(int i=1;i<=m;i++){
        int u,v,f,c;scanf("%d%d%d%d",&u,&v,&f,&c);
        adde(u,v,f,c);
    }
    mincost_maxflow();
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值