• POJ2516K次费用流建图


    Description:
      N个订单(每个订单订K种商品),M个供应商(每个供应商供应K种商品),K种商品,后N行,表示每一个订单的详细信息,后M行表示每个供应商供应的详细信息,后K 个N * M的矩阵表示第m个供应商送第k种商品到第n个订单的花费

    Solution:
      建图,分商品来建,对于第k种商品:
      · 源点连N个订单对于该商品的需求,费用0,容量为需求量

      ·N个订单对应连M个供应商,费用为第k个矩阵中对于的费用,容量为inf

      ·M个供应商链接汇点,费用0,容量为供应量

    Code:

      小错误还是很多,基本操作,一开始开的空间计算错误,加边操作中对于反向边的val和cost操作反了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #define inf (1 << 28)
    using namespace std;
    const int maxn = 111;
    const int maxk = 111;
    const int maxm = 111*111*2;
    
    int need[maxn][maxk];
    int have[maxn][maxm];
    int cost[maxm][maxn];
    int allneed[maxk];
    int allhave[maxk];
    int n,m,k;
    
    struct node
    {
        int to,val,cost,pre;
    }e[maxm];
    int id[maxn * 4];
    int cnt;
    void add(int from,int to,int val,int cost)
    {
        e[cnt].to = to;
        e[cnt].val = val;
        e[cnt].cost = cost;
        e[cnt].pre = id[from];
        id[from] = cnt++;
        swap(from,to);
        e[cnt].to = to;
        e[cnt].val = 0;
        e[cnt].cost = -cost;
        e[cnt].pre = id[from];
        id[from] = cnt++;
    }
    void init()
    {
        memset(allhave,0,sizeof(allhave));
        memset(allneed,0,sizeof(allneed));
        memset(id,-1,sizeof(id));
        cnt = 0;
    }
    

     spfa 版mcmf算法,一开始忘了加vis数组了,花费的计算算成了一整段的,应该分段计算花费

    int dis[maxn];
    int pre[maxn];
    int path[maxn];
    int vis[maxn];
    
    bool spfa(int s,int t)
    {
        memset(pre,-1,sizeof(pre));
        memset(vis,0,sizeof(vis));
        for(int i = 0;i < maxn ;++i)
            dis[i] = inf;
        dis[s] = 0;
        vis[s] = 1;
        queue<int> q;
        q.push(s);
        while(q.size())
        {
            int now = q.front();
            q.pop();
    
            for(int i = id[now];~i;i = e[i].pre)
            {
                int to = e[i].to;
                int val = e[i].val;
                int cost = e[i].cost;
    
                if(val > 0 && dis[now] + cost < dis[to])
                {
                    dis[to] = dis[now] + cost;
                    pre[to] = now;
                    path[to] = i;
                    if(!vis[to])
                    {
                        vis[to] = 1;
                        q.push(to);
                    }
                }
            }
            vis[now] = 0;
        }
        if(pre[t] == -1)return false;
        return true;
    }
    int mcmf(int s,int t)
    {
        int c = 0;
        while(spfa(s,t))
        {
            int mf = inf;
            for(int now = t;now != s;now = pre[now])
            {
                if(e[path[now]].val < mf)
                    mf = e[path[now]].val;
            }
            for(int now = t;now != s;now = pre[now])
            {
                e[path[now]].val -= mf;
                e[path[now]^1].val += mf;
                c += mf * e[path[now]].cost;
            }
        }
        return c;
    }
    

     建图操作

     对于供应商到汇点的加边操作,放错了循环……

    int main()
    {
        int ans;//最小费用
        int s,t;//源点汇点
        while(~scanf("%d%d%d",&n,&m,&k),n+m+k)
        {
            init();
            ans = 0;
            s = 0;
            t = n + m + 1;
            //第i个订单对于第j种商品的需求量
            for(int i = 1;i <= n;++i)
            {
                for(int j = 1;j <= k;++j)
                {
                    scanf("%d",&need[i][j]);
                    allneed[j] += need[i][j];
                }
            }
            //第i个供应商对于第j种商品的供应量
            for(int i = 1;i <= m;++i)
            {
                for(int j = 1;j <= k;++j)
                {
                    scanf("%d",&have[i][j]);
                    allhave[j] += have[i][j];
                }
            }
            int flag = 1;//需求是否能被满足
            for(int i = 1;i <= k;++i)
            {
                memset(id,-1,sizeof(id));
                cnt = 0;
    
                if(allhave[i] < allneed[i])
                    flag = 0;
    
                for(int j = 1;j <= n;++j)
                {
                    add(s,j,need[j][i],0);
                    for(int l = 1;l <= m;++l)
                    {
                        scanf("%d",&cost[l][j]);
                        if(!flag)continue;
                        add(j,n+l,inf,cost[l][j]);
                    }
                }
                for(int l = 1;l <= m;++l)
                    add(n+l,t,have[l][i],0);
    
                if(!flag)continue;
                ans += mcmf(s,t);
            }
            if(!flag)printf("-1
    ");
            else printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    jQueryrocket
    jQueryrocket
    jQueryrocket
    jQueryrocket
    jQueryrocket
    SPListItem.UpdateOverwriteVersion()真的不会创建新版本吗?
    不能访问本地服务器场。没有注册带有FeatureDependencyId 的 Cmdlet
    SharePoint 2013 另一个程序正在使用此文件,进程无法访问。 (异常来自 HRESULT:0x80070020)
    使用PowerShell修改操作系统“环境变量”
    无法解决“Microsoft.SharePoint.Security, Version=15.0.0.0,”与“Microsoft.SharePoint.Security, Version=14.0.0.0”之间的冲突
  • 原文地址:https://www.cnblogs.com/DF-yimeng/p/9703311.html
Copyright © 2020-2023  润新知