Minimum Cost POJ - 2516

相信很多人都是TLE了跑过来看题解的(我也是。。。。
思路:我们可以每种商品单独处理,跑k次最小费用流,比一起处理的复杂度会小很多

#include 
#include 
#include 
#include 
typedef long long LL;
using namespace std;
const int maxn = 1e7;
int INF = 1e8;
int read(){
    int w=1,q=0;char ch=' ';
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')q=q*10+ch-'0',ch=getchar();
    return w*q;
}

struct Edge
{
    int to, next, cap, cost;
} edge[maxn * 2];

int k, head[maxn];

void add(int a, int b, int w, int c){
    edge[k].to = b;
    edge[k].cap = w;
    edge[k].cost = c;
    edge[k].next = head[a];
    head[a] = k++;

    edge[k].to = a;
    edge[k].cap = 0;
    edge[k].cost = -c;
    edge[k].next = head[b];
    head[b] = k++;
}

int dis[maxn], vis[maxn], flow[maxn], pre[maxn];
int res = 0;

int Flody(int s, int t, int f){
    while(f > 0){
        for(int i = 0; i <= t; i++){
            dis[i] = INF, vis[i] = 0, pre[i] = -1, flow[i] = INF;
        }
        dis[s] = 0;
        queue<int> que;
        que.push(s);
        vis[s] = 1, flow[s] = INF;
        while(que.size()){
            int u = que.front();
            que.pop();
            vis[u] = 0;
            for(int i = head[u]; i != -1; i = edge[i].next){
                int to = edge[i].to, w = edge[i].cap, c = edge[i].cost;
                if(w && dis[to] > dis[u] + c){
                    flow[to] = min(flow[u], w);
                    dis[to] = dis[u] + c;
                    pre[to] = i;
                    if(!vis[to]){
                        que.push(to);
                        vis[to] = 1;
                    }
                }
            }
        }
        if(dis[t] == INF){
            break;
        }
        for(int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]){
            edge[i].cap -= flow[t];
            edge[i ^ 1].cap += flow[t];
        }
        f -= flow[t];
        res += dis[t] * flow[t];
    }
    if(f == 0) return 1;
    return 0;
}
int need[55][55], have[55][55];
int sumn[55], sumh[55];
int main(int argc, char const *argv[])
{
    int n, m, cnt;
    while(1){
        k = 0, res = 0;
        n = read(), m = read(), cnt = read();
        if(!n && !m && !cnt){
            break;
        }
        int s = 0, t = n + m + 1;
        for(int i = 1; i <= cnt; i++){
            sumn[i] = 0;
        }
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= cnt; j++){
                int x = read();
                need[i][j] = x;
                sumn[j] += x;
            }
        }

        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= cnt; j++){
                int x = read();
                have[i][j] = x;
            }
        }

        int flag = 1;
        for(int r = 1; r <= cnt; r++){
            k = 0;
            for(int i = 0; i <= t; i++){
                head[i] = -1;
            }
            for(int i = 1; i <= n; i++){
                add(i + m, t, need[i][r], 0);
            }
            for(int i = 1; i <= m; i++){
                add(s, i, have[i][r], 0);
            }
            for(int i = 1; i <= n; i++){
                for(int j = 1; j <= m; j++){
                    int x = read();
                    add(j, i + m, INF, x);
                }
            }
            if(!flag){
                continue;
            }
            if(Flody(s, t, sumn[r]) == 0){
                flag = 0;
            }
        }
        
        if(flag){
            printf("%d\n", res);
        } else{
            printf("-1\n");
        }
    }
    return 0;
}

你可能感兴趣的:(网络流)