• POJ 2516 Minimum Cost


    问题:最小费用最大流

    思路:针对对每一个物品建立网络流图求最小费用最大流,然后求和即可

    PS:mincost忘了每次都初始化为0,导致一直WA!用尽了半天的时间去寻找,蓦然回首,原来mincost没有初始化!

    View Code
    #include <stdio.h>
    #include <memory.h>

    #define N 52
    #define N2 104
    #define M 5202
    #define MAXVAL 0xfffffff
    #define MOV(x) (x=(x+1)%N2)

    int n,m,k,s,t;
    int need[N][N],supply[N][N];
    int nodevp[N2],nodeu[M],flow[M],cost[M],next[M],ind;

    int getPartDataAndCheck()//首先得到need和supply的数据判断是否供大于求
    {
    int i,j;

    scanf("%d %d %d",&n,&m,&k);
    if(0==n) return 0;

    for(i=1;i<=n;i++)
    for(j=1;j<=k;j++)
    scanf("%d",need[i]+j);
    for(i=1;i<=m;i++)
    for(j=1;j<=k;j++)
    scanf("%d",supply[i]+j);
    for(i=1;i<=k;i++)
    {
    need[0][i]=0;
    for(j=1;j<=n;j++)
    need[0][i]+=need[j][i];
    supply[0][i]=0;
    for(j=1;j<=m;j++)
    supply[0][i]+=supply[j][i];

    if(need[0][i]>supply[0][i]) return -1;
    }

    return 1;
    }

    void eatData(int lineNum)//“吃数据”
    {
    // char s[100];
    // while(lineNum--) gets(s);

    char ch;
    while((ch=getchar())=='\n' || ch==' ');
    while(lineNum--) while((ch=getchar())!='\n');

    }

    void addedge(int v,int u,int fw,int ct)
    {
    nodeu[ind]=u;
    flow[ind]=fw;
    cost[ind]=ct;
    next[ind]=nodevp[v];
    nodevp[v]=ind++;
    }

    void buildGraph(int goodsNum)//以编号为goodsNum的物品,进行建图
    {
    int i,j,val;

    s=0; t=m+n+1;
    memset(nodevp,-1,sizeof(nodevp)); ind=0;
    for(i=1;i<=m;i++)
    if(supply[i][goodsNum])//去除不需要建的边
    addedge(s,i,supply[i][goodsNum],0) , addedge(i,s,0,0);
    for(i=1;i<=n;i++)
    if(need[i][goodsNum])//去除不需要建的边
    addedge(i+m,t,need[i][goodsNum],0) , addedge(t,i+m,0,0);
    for(i=1;i<=n;i++)
    {
    if(0==need[i][goodsNum]) eatData(1);//去除不需要建的边
    else
    {
    for(j=1;j<=m;j++)
    {
    scanf("%d",&val);
    if(supply[j][goodsNum])//去除不需要建的边
    addedge(j,i+m,MAXVAL,val) , addedge(i+m,j,0,-val);
    }
    }
    }

    }

    int queue[N2],font,rear;
    int inqueue[N2],pre[N2],dist[N2];
    int SPFA()
    {
    int i,v,u;
    for(i=1;i<=t;i++) dist[i]=MAXVAL; dist[s]=0;
    memset(inqueue,0,sizeof(inqueue));
    memset(pre,-1,sizeof(pre));
    font=rear=0; queue[MOV(rear)]=s; inqueue[s]=1;

    while(font!=rear)
    {
    v=queue[MOV(font)]; inqueue[v]=0;
    for(i=nodevp[v];~i;i=next[i])
    {
    u=nodeu[i];
    if(flow[i] && dist[u]>dist[v]+cost[i])
    {
    dist[u]=dist[v]+cost[i]; pre[u]=i;
    if(!inqueue[u]) queue[MOV(rear)]=u,inqueue[u]=1;
    }
    }
    }

    if(dist[t]!=MAXVAL) return 1;
    else return 0;
    }

    int mincost_maxflow()
    {
    int i,minflow,mincost=0;
    while(SPFA())
    {
    minflow=MAXVAL;
    for(i=pre[t];~i;i=pre[nodeu[i^1]])
    if(minflow>flow[i])
    minflow=flow[i];
    for(i=pre[t];~i;i=pre[nodeu[i^1]])
    {
    mincost+=cost[i]*minflow;
    flow[i]-=minflow;
    flow[i^1]+=minflow;
    }
    }

    return mincost;
    }


    void solve()
    {
    int i,tmp,mincost; /* mincost=0; */
    while(tmp=getPartDataAndCheck())
    {
    if(tmp==-1)
    {
    eatData(k*n);
    printf("-1\n");
    }
    else
    {
    mincost=0;
    for(i=1;i<=k;i++)//针对每一个物品建图,求最小费用最大流!
    {
    buildGraph(i);
    mincost+=mincost_maxflow();
    }
    printf("%d\n",mincost);
    }
    }
    }

    int main()
    {
    // freopen("input.txt","r",stdin);

    solve();

    return 0;
    }



  • 相关阅读:
    数字校验1
    数字校验
    千分位保留4位小数
    如何把一个字符串格式化位4位一个空格
    from里button会提交表单
    重新学习JavaScript2015年11月3日
    java设计模式之代理模式
    自定义标签 (choose)
    自定义标签 foreach
    获取一个表格的一行的值
  • 原文地址:https://www.cnblogs.com/fornever/p/2426673.html
Copyright © 2020-2023  润新知