poj 2516 Mininum Cost

/* Name: poj 2516 Mininum Cost Author: UnimenSun Date: 11/06/11 09:20 Description: 最小费用最大流 */ /* 解题报告: 该题的难度为建图,可以自己加上两个结点一个为出点s,一个汇点t,出点先与supply相连, supply与shopkeeper连,shopkeeper与汇点连 同时由题意可以知道每种物品是相互独立的,因此可以将他们分开单独处理 建完图后,就可以用最小费用最大流处理了 注:该题的处理最小费用最大流的函数mcmf()是标准的处理该种类型的算法,可以当成模板使用 */ #include <iostream> #include <cstring> #include <queue> #include <algorithm> using namespace std; const int inf = 1000000000; int n, m, k; int s, t; int order[51][51], store[51][51], cost[51][51][51]; int cap[102][102], fee[102][102]; int flow[102][102], parent[102], d[102]; void mcmf() { memset(flow, 0, sizeof(flow)); queue<int> que; while(true) { //spfa算法开始 bool visited[102]; memset(visited, 0, sizeof(visited)); for(int i=1; i<=m+n+1; ++i) d[i] = inf; d[s] = 0; que.push(s); while(!que.empty()) { int u = que.front(); que.pop(); visited[u] = false; for(int v=0; v<=m+n+1; v++) { if(cap[u][v]>flow[u][v] && d[v]>d[u]+fee[u][v]) { d[v] = d[u]+fee[u][v]; parent[v] = u; if(!visited[v]) { visited[v] = true; que.push(v); } } } } //spfa结束 if(d[t] == inf) //汇点不可达,表明当前已是最小费用最大流 break; int a= inf; for(int u=t; u!=s; u=parent[u]) a=min(a, cap[parent[u]][u]-flow[parent[u]][u]); //计算可改进量 for(int u=t; u!=s; u=parent[u]) //增广 { flow[parent[u]][u] += a; flow[u][parent[u]] -= a; } } } int main() { while(true) { cin>>n>>m>>k; if(!n && !m && !k) break; for(int i=1; i<=n; ++i) for(int j=1; j<=k; ++j) cin>>order[i][j]; //第i个shopkeepers每种物品的定货量 for(int i=1; i<=m; ++i) for(int j=1; j<=k; ++j) cin>>store[i][j]; //第i个supply所能提供每每种物品的供货量 for(int tk=1; tk<=k; ++tk) for(int i=1; i<=n; ++i) for(int j=1; j<=m; ++j) cin>>cost[tk][j][i]; //第tk种物品从j到i的费用 //每个每个物品处理 s = 0; t = m + n + 1; bool bFlag = true; int ans = 0; for(int i=1; i<=k; ++i) { memset(cap, 0, sizeof(cap)); //建cap图 for(int j=1; j<=m; ++j) { cap[s][j] = store[j][i]; } for(int j=1; j<=m; ++j) { for(int tk=1; tk<=n; ++tk) { cap[j][tk+m] = store[j][i]; } } for(int j=1; j<=n; ++j) { cap[j+m][t] = order[j][i]; } //cap图建完 //建fee图 for(int j=1; j<=m; ++j) { for(int tk=1; tk<=n; tk++) { fee[j][tk+m] = cost[i][j][tk]; fee[tk+m][j] = -fee[j][tk+m]; } } //fee图建完 mcmf(); for(int j=1; j<=n; ++j) { if(cap[j+m][t] != flow[j+m][t]) { bFlag = false; break; } } if(!bFlag) { break; } for(int j=1; j<=m; ++j) { for(int tk=1; tk<=n; ++tk) { ans += flow[j][tk+m] * fee[j][tk+m]; } } } if(bFlag) cout<<ans<<endl; else cout<<-1<<endl; } return 0; }

你可能感兴趣的:(算法,Date)