题目链接: http://poj.org/problem?id=2516
说一下输入: 第一行是三个整数, n,m,k,分别代表n个商户,m个仓库,k种物品。 接着是n 行,每行k个整数, 意思是 在这 n 行中 , 第 i 行 第 j 列 就表示 第 i 个商户对 第 j 种物品的需求量。 然后是m 行,在这m 行中, 第 i 行第 j 列表示 第 j 种物品 放置在 第 i 个仓库的数量。接着是有 k 个矩阵,每个矩阵大小是 n*m, 三者整体就代表 第 K(1 <= K <= k) 种物品 位于 j 地点 运输到 i 商户 需要的费用。
思路: 就是最小费用最大流。 跑k次就可以了, 注意 每一次的最大流 应该和 全部商户对 第K 种物品的需求量相等,否则就是供不应求 输出-1;
关键是有思路,然后建图啊!!!!!!! 看了人家的思路才明白。 呼.... 菜是原罪
AC代码:
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxsize = 60;
const int maxn = 3000;
const int inf = 0x3f3f3f3f;
int need[maxsize][maxsize];
int locate[maxsize][maxsize];
struct node{
int u,v,cap,cost;
node(int u,int v,int cap,int cost):u(u),v(v),cap(cap),cost(cost){}
};
int vis[maxn];
int dis[maxn];
int pre[maxn];
int flow[maxn];
vector<node>edges;
vector<int> G[maxn];
void add(int u,int v,int cap,int cost){
edges.push_back(node(u,v,cap,cost));
edges.push_back(node(v,u,0,-cost));
int s = edges.size();
G[u].push_back(s - 2);
G[v].push_back(s - 1);
}
bool spfa(int s,int t,int &c,int &sum){
memset(vis,0,sizeof(vis));
memset(dis,inf,sizeof(dis));
memset(flow,0,sizeof(flow));
dis[s] = 0; vis[s] = 1;
flow[s] = inf;
queue<int> Q;
Q.push(s);
while(!Q.empty()){
int now = Q.front();
Q.pop(); vis[now] = 0;
for(int i = 0;i < G[now].size();i ++){
node &e = edges[G[now][i]];
if(e.cap > 0 && dis[e.v] > dis[now] + e.cost){
flow[e.v] = min(flow[now],e.cap);
dis[e.v] = dis[now] + e.cost;
pre[e.v] = G[now][i];
if(!vis[e.v]){
vis[e.v] = 1;
Q.push(e.v);
}
}
}
}
if(dis[t] == inf) return 0;
c += dis[t] * flow[t];
sum += flow[t];
int k = t;
while(k != s){
edges[pre[k]].cap -= flow[t];
edges[pre[k]^1].cap += flow[t];
k = edges[pre[k]].u;
}
return 1;
}
int main()
{
int n,m,k;
while(~scanf("%d%d%d",&n,&m,&k)){
if(!n && !m && !k) break;
for(int i = 1;i <= n;i ++){ ///第i 个商户对j 的需求
for(int j = 1;j <= k;j ++){
scanf("%d",&need[i][j]);
}
}
for(int i = 1;i <= m;i ++){ ///第i个仓库 对j 的储存
for(int j = 1;j <= k;j ++){
scanf("%d",&locate[i][j]);
}
}
int flag = 1,ans = 0;
for(int goods = 1;goods <= k;goods ++){ ///物资k
int c;
for(int i = 0;i < maxn;i ++) G[i].clear();
edges.clear();
for(int i = 1;i <= n;i ++){
for(int j = 1;j <= m;j ++){
scanf("%d",&c);
add(j,m + i,inf,c);
}
}
if(!flag) continue; ///有一次 供不应求 后面都不用再算了
for(int j = 1;j <= m;j ++){
add(0,j,locate[j][goods],0);
}
int sum = 0;
for(int i = 1;i <= n;i ++){
add(m + i,m + n + 1,need[i][goods],0);
sum += need[i][goods];
}
int all = 0,co = 0; ///co 是每一次的费用, ans 是总费用, all 是每一次的最大流
while(spfa(0,m + n + 1,co,all)); ///min_cost_maxflow
// printf("all : %d\nsum: %d\n",all,sum);
if(all != sum) flag = 0;
ans += co;
}
if(flag) printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}