★ POJ 2516 最小费用最大流(分开计算,K次费用流)

来源:互联网 发布:多媒体教学软件 编辑:程序博客网 时间:2024/05/18 01:58

题意:给你m个供货源,n个店,k种商品,每个店对于每种商品的需求量以及每个供货源运送k种商品到相应店的费用,求最小费用。


分析:

1、直接暴力n*k+m*k个点建图加剪枝勉强过。

2、正解,对于每种物品,分开计算最小费用,最后相加即可。


代码1:

//O(Kn^2m)//如果要求最大费用的话 只需在加边的时候加-的边  输出时输出-ans即可#pragma comment(linker,"/STACK:102400000,102400000")#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <vector>#include <string>#include <math.h>#include <queue>#include <stack>#include <map>#include <set>using namespace std;typedef long long ll;   //记得必要的时候改成无符号const int maxn=5005;const int maxm=1000005;const int INF=1000000000;struct EdgeNode{    int from;    int to;    int flow;    int cost;    int next;}edge[maxm];int head[maxn],cnt;void add(int x,int y,int z,int c){    edge[cnt].from=x;edge[cnt].to=y;edge[cnt].flow=z;edge[cnt].cost=c;edge[cnt].next=head[x];head[x]=cnt++;    edge[cnt].from=y;edge[cnt].to=x;edge[cnt].flow=0;edge[cnt].cost=-c;edge[cnt].next=head[y];head[y]=cnt++;}void init(){    cnt=0;    memset(head,-1,sizeof(head));}int S,T,n,m;int d[maxn],in[maxn],pre[maxn];queue<int>Q;bool spfa(int S,int T){    int u,v,f,c;    while(!Q.empty())Q.pop();    memset(in,0,sizeof(in));    for(int i=0;i<=n;i++)d[i]=INF;    d[S]=0;    Q.push(S);    while(!Q.empty())    {        u=Q.front(); Q.pop(); in[u]=0;        for(int i=head[u];i!=-1;i=edge[i].next){            v=edge[i].to; f=edge[i].flow; c=edge[i].cost;            if(f&&d[u]+c<d[v]){                d[v]=d[u]+c; pre[v]=i;                if(!in[v]){                    in[v]=1;                    Q.push(v);                }            }        }    }    if(d[T]==INF)return false;    return true;}int MCMF(int S,int T,int need=0){    int u;    int max_flow=0;    int min_cost=0;    while(spfa(S,T))    {        int flow=INF;        u=T;        while(u!=S){            flow=min(flow,edge[pre[u]].flow);            u=edge[pre[u]].from;        }        u=T; max_flow+=flow; min_cost+=d[T]*flow;        while(u!=S){            edge[pre[u]].flow-=flow;            edge[pre[u]^1].flow+=flow;            u=edge[pre[u]].from;        }    }    return min_cost;}int mp[55][55],you[55][55];int co[55][55][55],a[55],b[55];int main(){    int i,j,l,k,x,y;    while(~scanf("%d%d%d",&n,&m,&k)&&(n+m+k))    {        init(); S=0; T=m*k+n*k+1;        memset(a,0,sizeof(a));        memset(b,0,sizeof(b));        for(i=1;i<=n;i++)for(j=1;j<=k;j++)scanf("%d",&mp[i][j]),a[j]+=mp[i][j];        for(i=1;i<=m;i++)for(j=1;j<=k;j++)scanf("%d",&you[i][j]),b[j]+=you[i][j];        for(i=1;i<=k;i++){            for(j=1;j<=n;j++){                for(l=1;l<=m;l++)scanf("%d",&co[i][j][l]);            }        }        for(i=1;i<=k;i++)if(b[i]<a[i])break;        if(i<=k){            printf("-1\n");            continue;        }        for(i=1;i<=m;i++){            for(j=1;j<=k;j++){                y=(i-1)*k+j;                add(S,y,you[i][j],0);            }        }        for(i=1;i<=n;i++){            for(j=1;j<=k;j++){                x=m*k+(i-1)*k+j;                add(x,T,mp[i][j],0);            }        }        for(i=1;i<=m;i++){            for(j=1;j<=k;j++){                for(l=1;l<=n;l++){                    x=(i-1)*k+j;                    y=m*k+(l-1)*k+j;                    add(x,y,you[i][j],co[j][l][i]);                }            }        }        n=T+1;        printf("%d\n",MCMF(S,T));    }    return 0;}


代码2:

//O(Kn^2m)//如果要求最大费用的话 只需在加边的时候加-的边  输出时输出-ans即可#pragma comment(linker,"/STACK:102400000,102400000")#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <vector>#include <string>#include <math.h>#include <queue>#include <stack>#include <map>#include <set>using namespace std;typedef long long ll;   //记得必要的时候改成无符号const int maxn=205;const int maxm=1000005;const int INF=1000000000;struct EdgeNode{    int from;    int to;    int flow;    int cost;    int next;}edge[maxm];int head[maxn],cnt;void add(int x,int y,int z,int c){    edge[cnt].from=x;edge[cnt].to=y;edge[cnt].flow=z;edge[cnt].cost=c;edge[cnt].next=head[x];head[x]=cnt++;    edge[cnt].from=y;edge[cnt].to=x;edge[cnt].flow=0;edge[cnt].cost=-c;edge[cnt].next=head[y];head[y]=cnt++;}void init(){    cnt=0;    memset(head,-1,sizeof(head));}int S,T,n,m;int d[maxn],in[maxn],pre[maxn];queue<int>Q;bool spfa(int S,int T){    int u,v,f,c;    while(!Q.empty())Q.pop();    memset(in,0,sizeof(in));    for(int i=0;i<maxn;i++)d[i]=INF;    d[S]=0;    Q.push(S);    while(!Q.empty())    {        u=Q.front(); Q.pop(); in[u]=0;        for(int i=head[u];i!=-1;i=edge[i].next){            v=edge[i].to; f=edge[i].flow; c=edge[i].cost;            if(f&&d[u]+c<d[v]){                d[v]=d[u]+c; pre[v]=i;                if(!in[v]){                    in[v]=1;                    Q.push(v);                }            }        }    }    if(d[T]==INF)return false;    return true;}int MCMF(int S,int T,int need=0){    int u;    int max_flow=0;    int min_cost=0;    while(spfa(S,T))    {        int flow=INF;        u=T;        while(u!=S){            flow=min(flow,edge[pre[u]].flow);            u=edge[pre[u]].from;        }        u=T; max_flow+=flow; min_cost+=d[T]*flow;        while(u!=S){            edge[pre[u]].flow-=flow;            edge[pre[u]^1].flow+=flow;            u=edge[pre[u]].from;        }    }    return min_cost;}int mp[55][55],you[55][55];int co[55][55][55],a[55],b[55];void build(int x){    int i,j;    init(); S=0; T=n+m+1;    for(i=1;i<=m;i++)add(S,i,you[i][x],0);    for(i=1;i<=m;i++){        for(j=1;j<=n;j++){            add(i,m+j,you[i][x],co[x][j][i]);        }    }    for(i=1;i<=n;i++)add(m+i,T,mp[i][x],0);}int main(){    int i,j,l,k,x,y,sum;    while(~scanf("%d%d%d",&n,&m,&k)&&(n+m+k))    {        init(); sum=0;        memset(a,0,sizeof(a));        memset(b,0,sizeof(b));        for(i=1;i<=n;i++)for(j=1;j<=k;j++)scanf("%d",&mp[i][j]),a[j]+=mp[i][j];        for(i=1;i<=m;i++)for(j=1;j<=k;j++)scanf("%d",&you[i][j]),b[j]+=you[i][j];        for(i=1;i<=k;i++){            for(j=1;j<=n;j++){                for(l=1;l<=m;l++)scanf("%d",&co[i][j][l]);            }        }        for(i=1;i<=k;i++)if(b[i]<a[i])break;        if(i<=k){            printf("-1\n");            continue;        }        for(i=1;i<=k;i++){            build(i);            sum+=MCMF(S,T);        }        printf("%d\n",sum);    }    return 0;}


0 0