zoukankan      html  css  js  c++  java
  • [网络流24题(5/24)] 分配问题(最小费用最大流)

    传送门

    分析:

    非常经典的费用流的模型吧,也可以通过二分图最大匹配去做,但是鉴于二分图最大匹配的算法存在一定的局限性,故还是学一学较为通用的费用流的做法。

    这道题目中本质上要讨论的问题跟运输问题,运输问题是一致的。

    因为考虑到每个人只能被分配到一种货物,每种货物只能被一个人所分配,因此,我们不妨用流量将他们限流。

    我们创建一个超级源地(sp),将(sp)跟每个人连一条流量为(1),费用为(0)的边。

    同时我们创建一个超级汇点(ep),将每一种货物跟(ep)都连一条流量为(1),费用为(0)的边。

    同时,对于每一个人和货物,我们对他们连一条流量为无穷的边。

    因为每个人只能从超级源点获取最多(1)点的流量,每种货物只能向超级汇点传送最多(1)点的流量,因此当这个图满流时,能够保证每个人一定会配对最多一个货物,即达到我们限流的要求。

    而如果我们需要求解最小花费,我们只需要将人和货物的边加上的费用取(val_{ij}),最后在这张图上跑最小费用最大流后最小费用即为答案。

    而如果我们需要求解最大花费,我们只需要将人和货物的边加上的费用取相反数(-val_{ij}),最后在这张图上跑最小费用最大流后最小费用的相反数即为答案。

    代码:

    #include <bits/stdc++.h>
    #define maxn 4050
    using namespace std;
    struct Node{
        int to,next,val,cost;
    }q[maxn<<1];
    int head[maxn],cnt=0;
    int dis[maxn],vis[maxn],sp,ep,maxflow,cost;
    int n,num[maxn][maxn];
    const int INF=0x3f3f3f3f;
    void init(){
        memset(head,-1,sizeof(head));
        cnt=2;
        maxflow=cost=0;
    }
    void addedge(int from,int to,int val,int cost){
        q[cnt].to=to;
        q[cnt].next=head[from];
        q[cnt].val=val;
        q[cnt].cost=cost;
        head[from]=cnt++;
    }
    void add_edge(int from,int to,int val,int cost){
        addedge(from,to,val,cost);
        addedge(to,from,0,-cost);
    }
    bool spfa(){
        memset(vis,0,sizeof(vis));
        memset(dis,0x3f,sizeof(dis));
        dis[sp]=0;
        vis[sp]=1;
        queue<int>que;
        que.push(sp);
        while(!que.empty()){
            int x=que.front();
            que.pop();
            vis[x]=0;
            for(int i=head[x];i!=-1;i=q[i].next){
                int to=q[i].to;
                if(dis[to]>dis[x]+q[i].cost&&q[i].val){
                    dis[to]=dis[x]+q[i].cost;
                    if(!vis[to]){
                        que.push(to);
                        vis[to]=1;
                    }
                }
            }
        }
        return dis[ep]!=0x3f3f3f3f;
    }
    int dfs(int x,int flow){
        if(x==ep){
            vis[ep]=1;
            maxflow+=flow;
            return flow;
        }//可以到达t,加流
        int used=0;//该条路径可用流量
        vis[x]=1;
        for(int i=head[x];i!=-1;i=q[i].next){
            int to=q[i].to;
            if((vis[to]==0||to==ep)&&q[i].val!=0&&dis[to]==dis[x]+q[i].cost){
                int minflow=dfs(to,min(flow-used,q[i].val));
                if(minflow!=0){
                    cost+=q[i].cost*minflow;
                    q[i].val-=minflow;
                    q[i^1].val+=minflow;
                    used+=minflow;
                }
                //可以到达t,加费用,扣流量
                if(used==flow)break;
            }
        }
        return used;
    }int mincostmaxflow(){
        while(spfa()){
            vis[ep]=1;
            while(vis[ep]){
                memset(vis,0,sizeof(vis));
                dfs(sp,INF);
            }
        }
        return maxflow;
    }
    int main()
    {
        scanf("%d",&n);
        init();
        sp=2*n+1,ep=2*n+2;
    
        for(int i=1;i<=n;i++){
            add_edge(sp,i,1,0);
            add_edge(i+n,ep,1,0);
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&num[i][j]);
                add_edge(i,j+n,INF,num[i][j]);
            }
        }
        mincostmaxflow();
        printf("%d
    ",cost);
    
        init();
        for(int i=1;i<=n;i++){
            add_edge(sp,i,1,0);
            add_edge(i+n,ep,1,0);
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                add_edge(i,j+n,INF,-num[i][j]);
            }
        }
        mincostmaxflow();
        printf("%d
    ",-cost);
        return 0;
    }
    
  • 相关阅读:
    Quicksum -SilverN
    uva 140 bandwidth (好题) ——yhx
    uva 129 krypton factors ——yhx
    uva 524 prime ring problem——yhx
    uva 10976 fractions again(水题)——yhx
    uva 11059 maximum product(水题)——yhx
    uva 725 division(水题)——yhx
    uva 11853 paintball(好题)——yhx
    uva 1599 ideal path(好题)——yhx
    uva 1572 self-assembly ——yhx
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11379351.html
Copyright © 2011-2022 走看看