luoguのP4015(最小コスト最大フロー)

ポータル

質問の意味:

そこ\(m個\)倉庫および\(\ N-)小売業者、\(Iは\)セクションに倉庫\(J \)小売業者がかかり\(V [I] [J ] \) 元。今、私たちは、最小のコストおよび最大コストを求め、収穫や倉庫小売店の同じ量を供給する必要があります。

分析:

最小コスト最大流量の非常に古典的なモデル。あなたはフローのバランスを表し、同じ電源と収穫を、確認したいので、私たちはスーパーのソースにすることができますので\(SPの\)を倉庫に対応しても流量で(a_iを\)\、コスト\(0 \)側に、スーパーミーティングポイントと対応する小売業者せながら\(欧州\)も流\(b_i \)コスト(\ 0 \)側。倉庫や小売店ではなく、倉庫や小売業者の間でもトラフィックのために我々は唯一の無限のコスト必要な\(V [i]の[J ] \) 側を。

最小コストのために、私たちは、上図の最小コストの最大フローを実行する必要があります。

最大コストの問題については、我々は唯一の無限の、コストの均一な流れ上のグラフの倉庫や小売業者に変更する必要があります\( - V [i]は[ J] \) 側に、そして最終的には新マップで反対の答えである最小数の最終的なコストが、最小コスト、最大フローに実行しています。

コード:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 505;
const int maxm = 20005;
int head[maxn],cnt=0;
int dis[maxn],vis[maxn],sp,ep,maxflow,cost;
const int INF=0x3f3f3f3f;
struct Node{
    int to,next,val,cost;
}q[maxm<<1];
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;
    }
    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;
            }
            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 a[maxn],b[maxn],v[maxn][maxn];
int main()
{
    int n,m;
    init();
    scanf("%d%d",&n,&m);
    sp=n+m+1,ep=n+m+2;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        add_edge(sp,i,a[i],0);
    }
    for(int i=1;i<=m;i++){
        scanf("%d",&b[i]);
        add_edge(i+n,ep,b[i],0);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&v[i][j]);
            add_edge(i,j+n,INF,v[i][j]);
        }
    }
    mincostmaxflow();
    printf("%d\n",cost);
    init();
    for(int i=1;i<=n;i++){
        add_edge(sp,i,a[i],0);
    }
    for(int i=1;i<=m;i++){
        add_edge(i+n,ep,b[i],0);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            add_edge(i,j+n,INF,-v[i][j]);
        }
    }
    mincostmaxflow();
    printf("%d\n",-cost);
    return 0;
}

おすすめ

転載: www.cnblogs.com/Chen-Jr/p/11348138.html