最小费.
主要是这题有K种货物搞得关系很复杂, 开始建图卡住, 其实把k种货物分开来建k次图跑k次就好了.
然后判断最大流和是否满足需求, 若满足则输出最小费和, 若不满足, 则输出-1.
貌似还可以用KM
代码:
//最小费用流 // 建k次图... 最小费 #include<iostream> #include<queue> #include<cstring> #include<cstdio> using namespace std; const int MAXN = 200; const int MAXM = 40005; const int INF = 1<<30; int mincost,maxflow; int n,m; int U[MAXM],V[MAXM],cap[MAXM],flow[MAXM],cost[MAXM],next[MAXM]; int head[MAXN],pre[MAXN],Edge[MAXN],dis[MAXN]; int num; void addEdge(int u,int v,int Cap,int Cost) { flow[num] = flow[num+1] = 0; V[num] = v; U[num] = u; cap[num] = Cap; cost[num] = Cost; next[num] = head[u]; head[u] = num++; V[num] = u; U[num] = v; cap[num] = 0; cost[num] = -Cost; next[num] = head[v]; head[v] = num++; } void MCMF(int st,int ed) { queue<int> q; memset(flow,0,sizeof(flow)); mincost = maxflow = 0; for(;;) { bool inq[MAXN]; for(int i = st;i <= ed;++i) dis[i] = (i == st ? 0 : INF); memset(inq,0,sizeof(inq)); q.push(st); while(!q.empty()) { int u = q.front(); q.pop(); inq[u] = 0; for(int e = head[u];e != -1;e = next[e]) { if(cap[e] > flow[e] && dis[u] + cost[e] < dis[V[e]]) { dis[V[e]] = dis[u] + cost[e]; pre[V[e]] = U[e]; Edge[V[e]] = e; if(!inq[V[e]]) { q.push(V[e]); inq[V[e]] = 1; } } } }//SPFA增广 if(dis[ed] == INF) break; int delta = INF;//delta为可改进量 for(int u = ed;u != st;u = pre[u]) delta = min(delta,cap[Edge[u]] - flow[Edge[u]]);//遍历最短路径的边,并修改可改进量 for(int u = ed;u != st;u = pre[u]) { flow[Edge[u]] += delta;//更新正向流量 flow[Edge[u] ^ 1] -= delta;//通过异或1取得反向边的序号,并更新反向流量 } mincost += dis[ed] * delta; maxflow += delta; } } int sell[52][52]; int buy[52][52]; int value[52][52][52]; int main() { // buildGraphs int K; while(scanf("%d%d%d", &n, &m, &K) == 3) { if(!n && !m && !K) break; int need = 0; int totflow = 0; int totcost = 0; for(int i=0; i<n; i++) for(int k=0; k<K; k++) { scanf("%d", &buy[k][i]); //n个买家 need+=buy[k][i]; } for(int i=0; i<m; i++) for(int k=0; k<K; k++) { scanf("%d", &sell[k][i]); //m个仓库 } for(int k=0; k<K; k++) for(int i=0; i<n; i++) for(int j=0; j<m; j++) { scanf("%d", &value[k][i][j]); //j->i } for(int k=0; k<K; k++) { num = 0; memset(head,-1,sizeof(head)); // 0 卖 1~m 买 m+1~m+n 汇 m+n+1 for(int i=0; i<m; i++) { addEdge(0,i+1,sell[k][i],0); } for(int i=0; i<n; i++) { addEdge(i+1+m, m+n+1, buy[k][i], 0); } for(int i=0; i<n; i++) for(int j=0; j<m; j++) //卖 { addEdge(j+1, i+1+m, INF, value[k][i][j]); } //MCMF MCMF(0,n+m+1); totcost += mincost; totflow += maxflow; //printf("%d\n",mincost); } if(totflow!=need) totcost = -1; printf("%d\n", totcost); } }