hdu 4322 最大费用流

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4322

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;

const int maxe = 50000;
const int maxn = 30;
const int INF  = 0x3f3f3f;

struct Edge{
    int u,v,flow,cap,cost;
    int next;
    Edge(int u=0,int v=0,int flow=0,int cap=0,int cost=0,int next=0):
        u(u), v(v),  flow(flow), cap(cap),  cost(cost), next(next) {}
};

struct MCMF{
    int d[maxn];
    bool inq[maxn];
    Edge edges[maxe];
    int head[maxn],cnt;
    int pa[maxn];   //用于回溯找增广路。
    int res[maxn];

    void init(){
        memset(head,-1,sizeof(head));
        cnt = 0;
    }

    void addedge(int u,int v,int cap,int cost){
        edges[cnt] = Edge(u,v,0,cap,cost,head[u]);
        head[u] = cnt++;
        edges[cnt] = Edge(v,u,0,0,-cost,head[v]);
        head[v] = cnt++;
    }

    bool SPFA(int s,int t,int& flow,int& cost){
        memset(inq,0,sizeof(inq));
        memset(d,-0x3f,sizeof(d));     //这个才是WA无数次的原因,看别人的代码才知道。
        queue<int> Q;
        Q.push(s);
        d[s] = 0;        inq[s] = true;
        res[s] = INF;    res[t] = 0;
        while(!Q.empty()){
            int u = Q.front();  Q.pop();
            inq[u] = false;
            for(int i=head[u];i!=-1;i=edges[i].next){
                Edge& e = edges[i];
                if(e.cap > e.flow && d[e.v] < d[u] + e.cost){
                     d[e.v] = d[u] + e.cost;
                     pa[e.v] = i;
                     res[e.v] = min(res[u],e.cap-e.flow);
                     if(!inq[e.v]){
                        Q.push(e.v);   inq[e.v] = true;
                     }
                }
            }

        }
        if(res[t] == 0)  return false;
        flow += res[t];
        cost += res[t]*d[t];
        for(int i=t;i!=s;i=edges[pa[i]].u){
            edges[pa[i]].flow   += res[t];
            edges[pa[i]^1].flow -= res[t];
        }
        return true;
    }

    bool MaxCost(int s,int t,int N,int sumB){
        int flow = 0,cost = 0;
        while(SPFA(s,t,flow,cost)) {}

        return N - flow >= sumB - cost;
    }
}solver;

int main()
{
    //freopen("E:\acm\input.txt","r",stdin);
    int T;
    cin>>T;
    for(int cas=1;cas<=T;cas++){
        solver.init();
        int N,M,K;
        cin>>N>>M>>K;
        int B[maxn];
        int sumB = 0;
        for(int i=1;i<=M;i++)  { cin>>B[i];  sumB += B[i]; }
        int s = 0, t = N+M+1;
        for(int i=1;i<=N;i++)  solver.addedge(s,i,1,0);


        int like[maxn][maxn];
         for(int i=1; i<=M; i++)
            for(int j=1; j<=N; j++){
                scanf("%d",&like[i][j]);
                if(like[i][j])
                    solver.addedge(j,i+N,1,0);
            }

 /**
        for(int i=1;i<=M;i++)
            for(int j=1;j<=N;j++){
                int flag;
                scanf("%d",&flag);
                if(flag)  solver.addedge(j,i+N,1,0);
            }
   这个代码与上面的那段功能相同,但我不知道为啥会错。我怀疑是oj的问题。
**/
        for(int i=1;i<=M;i++){
            solver.addedge(N+i,t,B[i]/K,K);
            if(B[i]%K > 1)
                solver.addedge(N+i,t,1,B[i]%K);

        }
        if(solver.MaxCost(s,t,N,sumB))  printf("Case #%d: YES
",cas);
        else                            printf("Case #%d: NO
",cas);
    }
}
View Code
原文地址:https://www.cnblogs.com/acmdeweilai/p/3273288.html