POJ 2516 Minimum Cost

来源:互联网 发布:车载音乐视频软件 编辑:程序博客网 时间:2024/05/17 23:38

最小费.

主要是这题有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(){//buildGraphsint 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+1for(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]);}//MCMFMCMF(0,n+m+1);totcost += mincost;totflow += maxflow;//printf("%d\n",mincost);}if(totflow!=need) totcost = -1;printf("%d\n", totcost);}}


原创粉丝点击