HDU5619 Jam's store(最小費用最大流 MCMF)

題意

n個顧客m個服務員,給出每個服務員給每個顧客服務需要的時間,求顧客最小的等待時間

建圖

網絡流真是玄學啊,就是不會建圖。。

  • 源點向每個客戶連邊,控制流量爲n
  • 服務員拆點,每個客戶向每個服務員連n條邊,表示是該服務員倒數第k個服務的對象,代價爲k*cost[i] [j]
  • 拆點後的服務員向匯點連邊

因此每個服務員會先確定最後一個服務的對象

代碼

#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define debug(a) printf("a =: %d\n",a);
#define sc(x) scanf("%d",&x)
const int INF=0x3f3f3f3f;
const int maxn=500+50;
const int Mod=1000000007;
const double PI=acos(-1);
typedef long long ll;
typedef unsigned int ui;
using namespace std;

struct Edge{
    int from,to,cap,flow,cost;

    Edge() {}

    Edge(int from, int to, int cap, int flow, int cost) : from(from), to(to), cap(cap), flow(flow), cost(cost) {}
};

struct MCMF{
    int m;
    vector<Edge> edges;
    vector<int> G[maxn];
    int inq[maxn];
    int d[maxn];
    int p[maxn];
    int a[maxn];

    void init(int n){
        for(int i=0;i<=n;i++) G[i].clear();
        edges.clear();
    }

    void addEdge(int from,int to,int cap,int cost){
        edges.push_back(Edge(from,to,cap,0,cost));
        edges.push_back(Edge(to,from,0,0,-cost));
        m=edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }

    bool spfa(int s,int t,int &flow,int &cost){
        mem(d,0x3f); mem(inq,0); mem(a,0);
        d[s]=0; inq[s]=1; p[s]=0; a[s]=INF;
        queue<int> qu;
        qu.push(s);
        while(!qu.empty()){
            int u=qu.front(); qu.pop();
            inq[u]=0;
            int sz=G[u].size();
            for(int i=0;i<sz;i++){
                Edge &edge=edges[G[u][i]];
                if(edge.cap>edge.flow && d[edge.to]>d[u]+edge.cost){
                    d[edge.to]=d[u]+edge.cost;
                    p[edge.to]=G[u][i];
                    a[edge.to]=min(a[u],edge.cap-edge.flow);
                    if(!inq[edge.to]){
                        qu.push(edge.to);
                        inq[edge.to]=1;
                    }
                }
            }
        }
        if(d[t]==INF) return false;
        flow+=a[t];
        cost+=d[t]*a[t];
        int u=t;
        while(u!=s){
            edges[p[u]].flow+=a[t];
            edges[p[u]^1].flow-=a[t];
            u=edges[p[u]].from;
        }
        return true;
    }

    int minCost(int s,int t){
        int flow=0,cost=0;
        while(spfa(s,t,flow,cost));
        //cout<<"flow "<<flow<<endl;
        return cost;
    }
};

int s[233][233];
MCMF mcmf;

int main()
{
#ifndef ONLINE_JUDGE
    //freopen("/home/martin/ClionProjects/untitled/in.txt","r",stdin);
    //freopen("/home/martin/ClionProjects/untitled/out.txt","w",stdout);
#endif
    int T; scanf("%d",&T);
    for(int cs=1;cs<=T;cs++){
        int n,m;
        scanf("%d %d",&m,&n);
        //scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&s[i][j]);

        int N=1+n+n*m;
        mcmf.init(N+1);
        for(int i=1;i<=n;i++)
            mcmf.addEdge(0,i,1,0);
        for(int j=1;j<=m;j++)
            for(int i=1;i<=n;i++){
                for(int k=1;k<=n;k++){
                    mcmf.addEdge(i,j*n+k,1,k*s[i][j]);
                }
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
              mcmf.addEdge(j*n+i,N,1,0);
        printf("%d\n",mcmf.minCost(0,N));
        //printf("Case #%d: %d\n",cs,mcmf.minCost(0,N));
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章