zoukankan      html  css  js  c++  java
  • poj2516

    题意:有k种物品,m个供应商,n个收购商。每个供应商和收购商都需要一些种类的物品若干。每个供应商与每个收购商之间的对于不同物品的运费是不同的。求满足收购商要求的情况下,最小运费。

    分析:最小费用最大流,最大流的前提下求最小费用。这题我们可以把k种物品分开计算,每次对一种物品进行最小费用最大流计算。如果不分开算会超时。对于每种物品,从源到供应商连接,容量为供应商的储存量,费用为0。采购商到汇连边,容量为需求量,费用为0。供应商到采购商连边,容量为无穷,费用为对应的运费。

    最小费用最大流的计算流程大致是:每次找到一条根据费用来看的最短路,然后对这条最短路进行增加流量,直到所有路径流量都不能增加为止。

    View Code
    #include <iostream>
    #include
    <cstdio>
    #include
    <cstdlib>
    #include
    <cstring>
    usingnamespace std;

    #define N 110
    #define E 10000
    #define inf 1000000000

    #define typef int
    // type of flow
    #define typec int
    // type of dis
    const typef inff =0x3f3f3f3f;
    // max of flow
    const typec infc =0x3f3f3f3f;
    // max of dis
    int shop[N][N], supply[N][N];
    struct network
    {
    int nv, ne, pnt[E], nxt[E];
    int vis[N], que[N], head[N], pv[N], pe[N];
    int sum;
    typef flow, cap[E];
    typec cost, dis[E], d[N];
    void addedge(int u, int v, typef c, typec w)
    {
    pnt[ne]
    = v;
    cap[ne]
    = c;
    dis[ne]
    =+w;
    nxt[ne]
    = head[u];
    head[u]
    = (ne++);
    pnt[ne]
    = u;
    cap[ne]
    =0;
    dis[ne]
    =-w;
    nxt[ne]
    = head[v];
    head[v]
    = (ne++);
    }
    int mincost(int src, int sink)
    {
    int i, k, f, r;
    typef mxf;
    for (flow =0, cost =0;;)
    {
    memset(pv,
    -1, sizeof(pv));
    memset(vis,
    0, sizeof(vis));
    for (i =0; i < nv; ++i)
    d[i]
    = infc;
    d[src]
    =0;
    pv[src]
    = src;
    vis[src]
    =1;
    for (f =0, r =1, que[0] = src; r != f;)
    {
    i
    = que[f++];
    vis[i]
    =0;
    if (N == f)
    f
    =0;
    for (k = head[i]; k !=-1; k = nxt[k])
    if (cap[k] && dis[k] + d[i] < d[pnt[k]])
    {
    d[pnt[k]]
    = dis[k] + d[i];
    if (0== vis[pnt[k]])
    {
    vis[pnt[k]]
    =1;
    que[r
    ++] = pnt[k];
    if (N == r)
    r
    =0;
    }
    pv[pnt[k]]
    = i;
    pe[pnt[k]]
    = k;
    }
    }
    if (-1== pv[sink])
    break;
    for (k = sink, mxf = inff; k != src; k = pv[k])
    if (cap[pe[k]] < mxf)
    mxf
    = cap[pe[k]];
    flow
    += mxf;
    cost
    += d[sink] * mxf;
    for (k = sink; k != src; k = pv[k])
    {
    cap[pe[k]]
    -= mxf;
    cap[pe[k]
    ^1] += mxf;
    }
    }
    return cost;
    }
    void build(int n, int m, int o)
    {
    nv
    = n + m +2;
    ne
    =0;
    int src =0;
    int sink =1;
    sum
    =0;
    memset(head,
    -1, sizeof(head));
    for (int i =0; i < n; i++)
    {
    addedge(i
    +2, sink, shop[i][o], 0);
    sum
    += shop[i][o];
    }
    for (int i =0; i < m; i++)
    addedge(src, i
    +2+ n, supply[i][o], 0);
    for (int i =0; i < n; i++)
    for (int j =0; j < m; j++)
    {
    int a;
    scanf(
    "%d", &a);
    addedge(j
    +2+ n, i +2, inf, a);
    }
    }
    };

    int n, m, o;

    void input()
    {
    for (int i =0; i < n; i++)
    for (int j =0; j < o; j++)
    scanf(
    "%d", &shop[i][j]);
    for (int i =0; i < m; i++)
    for (int j =0; j < o; j++)
    scanf(
    "%d", &supply[i][j]);
    }

    int main()
    {
    //freopen("t.txt", "r", stdin);
    while (scanf("%d%d%d", &n, &m, &o), n | m | o)
    {
    bool ok =true;
    int ans =0;
    input();
    for (int i =0; i < o; i++)
    {
    network g;
    g.build(n, m, i);
    if (ok)
    ans
    += g.mincost(0, 1);
    if (g.flow != g.sum)
    ok
    =false;
    }
    if (ok)
    printf(
    "%d\n", ans);
    else
    printf(
    "-1\n");
    }
    return0;
    }
  • 相关阅读:
    Java读取Excel文件的几种方法
    PowerDesigner的安装和数据库创建(转载)
    JAVA UUID 生成
    Mysql的“Limit”操作
    实现java 中 list集合中有几十万条数据,每100条为一组取出
    MySQL5中大数据错误:Packet for query is too large (****** > ******). You can change this value on the server by setting the max_allowed_packet' variable.;
    Mybatis 示例之 foreach
    JAVA WEB ------ 文件下载及导出数据到office Execl表格
    8 -- 深入使用Spring -- 4...3 AOP的基本概念
    8 -- 深入使用Spring -- 4...2 使用AspectJ实现AOP
  • 原文地址:https://www.cnblogs.com/rainydays/p/2049183.html
Copyright © 2011-2022 走看看