POJ-2516-最小费用最大流

来源:互联网 发布:mac 类似梦幻西游游戏 编辑:程序博客网 时间:2024/05/22 08:22

题目大意:n个商店,m个供货商,给出每个商店需要的货物和每个供货商能提供的货物和供货价格,问要使所有商店都能满足需求是最小费用是多少;

题目解析:构图,对每种货物求一次最小费用最大流,源(费用为0,容量为供货商的持有量)->供货商(费用,容量为inf)->商店->汇;

AC代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<queue>using namespace std;const int MAXN = 110;  const int MAXM = 100000;  const int INF = 0x3fffffff;  struct Edge  {      int to,next,cap,flow,cost;  } edge[MAXM];  int head[MAXM],tol;  int pre[MAXM],dis[MAXM];  bool vis[MAXM];  int start, end;void init()  {      tol = 0;      memset(head,-1,sizeof(head));  }  void addedge(int u,int v,int cap,int cost){      edge[tol].to = v;      edge[tol].cap = cap;      edge[tol].cost = cost;      edge[tol].flow = 0;      edge[tol].next = head[u];      head[u] = tol++;      edge[tol].to = u;      edge[tol].cap = 0;      edge[tol].cost = -cost;      edge[tol].flow = 0;      edge[tol].next = head[v];      head[v] = tol++;  }  bool spfa(int s,int t)  {      queue<int> q;      for(int i = 0; i < MAXM; i++)      {          dis[i] = INF;          vis[i] = false;          pre[i] = -1;      }      dis[s] = 0;      vis[s] = true;      q.push(s);      while(!q.empty())      {          int u = q.front();          q.pop();          vis[u] = false;          for(int i = head[u]; i != -1; i = edge[i].next)          {              int v = edge[i].to;              if(edge[i].cap > edge[i].flow &&                      dis[v] > dis[u] + edge[i].cost )              {                  dis[v] = dis[u] + edge[i].cost;                  pre[v] = i;                  if(!vis[v])                  {                      vis[v] = true;                      q.push(v);                  }              }          }      }      if(pre[t] == -1)      {          return false;      }      else          return true;  }  int minCostMaxflow(int s,int t,int &cost)  {      int flow = 0;      cost = 0;      while(spfa(s,t))      {          int Min = INF;          for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])          {              if(Min > edge[i].cap - edge[i].flow)                  Min = edge[i].cap - edge[i].flow;          }          for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])          {              edge[i].flow += Min;              edge[i^1].flow -= Min;              cost += edge[i].cost * Min;          }          flow += Min;      }      return flow;  }  int n,m,sum,k;int s[MAXN][MAXN],p[MAXN][MAXN];void build(int num){int i,j;sum=0;init();for(i=1;i<=m;i++)addedge(0,i,p[i][num],0);for(i=1;i<=n;i++){addedge(i+m,n+m+1,s[i][num],0);sum+=s[i][num];}for(i=1;i<=n;i++){for(j=1;j<=m;j++){int temp;scanf("%d",&temp);addedge(j,i+m,INF,temp);}}}int main(){while(scanf("%d%d%d",&n,&m,&k)!=EOF&&(n+m+k)){int i,j,ans=0;for(i=1;i<=n;i++)for(j=1;j<=k;j++)scanf("%d",&s[i][j]);for(i=1;i<=m;i++)for(j=1;j<=k;j++)scanf("%d",&p[i][j]);int flag=1;for(i=1;i<=k;i++){int f,a;build(i);if(flag){ f=minCostMaxflow(0,n+m+1,a);ans+=a;}if(f!=sum){flag=0;}}if(flag)printf("%d\n",ans);else printf("-1\n");}return 0;}


0 0
原创粉丝点击