hdu 4780 Candy Factory(最小费用流--按流建图)

hdu 4780 Candy Factory

这题的数据有点弱,本来应该考虑到一种情况:机器初始化后不马上生产而是转到另一种生产模式再开始生产。但没想到考虑了之后就wa了
反正是典型的最小费用流问题,一般都可以用两种方法来做:按源建图、按流建图
我这里采用按流建图的方法:用两点间的边(val=1,cost=-inf)代表一颗糖果生产,最后结果加上n*inf就行了。需要注意的是每个代表机器的点需要连一条到汇点的边(val=1,cost=0)表示该机器没有被用到。
#include<cstdio>
#include<queue>
using namespace std;
typedef __int64 ll;
const int MAXN = 550, MAXM = 105, iif = 0x3f3f3f3f;
const ll inf = ll(1)<<53;
struct _edge
{
    int v, next, val;
    ll cost;
    _edge(){}
}e[5000010];
int head[MAXN], cnt, fa[MAXN], vis[MAXN], pos[MAXN];
ll dis[MAXN];
inline void add(int u, int v, int val, ll c)
{
    e[cnt].v = v; e[cnt].val = val, e[cnt].cost = c; e[cnt].next = head[u];
    head[u] = cnt++;
    e[cnt].v = u; e[cnt].val = 0; e[cnt].cost = -c; e[cnt].next = head[v];
    head[v] = cnt++;
}
bool spfa(int s, int t)
{
    for(int i = 0; i<= t; ++i) fa[i]=-1,dis[i]=inf,vis[i]=0;
    int bg = 0, ed = 0;
    ll p;
    queue<int> q;
    q.push(s);
    dis[s] = 0; vis[s] = 1;
    while (!q.empty())
    {
        int u = q.front(); q.pop();
        vis[u] = 0;
        for (int i = head[u]; ~i; i=e[i].next)
        {
            int v = e[i].v;
            if (e[i].val > 0 && dis[v] > (p = dis[u]+e[i].cost))
            {
                dis[v] = p;
                fa[v] = u;
                pos[v] = i;
                if (!vis[v])
                {
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    return fa[t] != -1;
}
int tpm[MAXM], n, m, k;
void minCost_maxFlow(int s, int t)
{
    int f = 0;
    ll cost = 0;
    while (spfa(s,t))
    {
        for (int i=t; i!=s; i=fa[i])
            e[pos[i]].val--, e[pos[i]^1].val++;
        cost += dis[t];
    }
    for (int i = 0; i< n; ++i)
        f += e[tpm[i]].val;
    if (f != n) {printf("-1\n"); return;}
    printf("%I64d\n", cost+inf*n);
}
int st[MAXM][2], cc[MAXM][MAXM], dd[MAXM][MAXM], ee[MAXM][MAXM], ff[MAXM][MAXM];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int N, s, t;
    while(scanf("%d%d%d", &n, &m, &k) && (n+m+k) != 0)
    {
        s = m+2*n, t = s+1;
        cnt = 0;
        memset(head, -1, sizeof head);
        for (int i = 0; i< n; ++i)
            scanf("%d%d", &st[i][0], &st[i][1]);
        for (int i = 0; i< n; ++i)
        for (int j = 0; j< m; ++j)
            scanf("%d", &cc[i][j]);
        for (int i = 0; i< n; ++i)
        for (int j = 0; j< m; ++j)
            scanf("%d", &dd[i][j]);
           for (int i = 0; i< n; ++i)
        for (int j = 0; j< n; ++j)
            scanf("%d", &ee[i][j]);
           for (int i = 0; i< n; ++i)
        for (int j = 0; j< n; ++j)
            scanf("%d", &ff[i][j]);
        for (int i = 0, p; i< m; ++i)
        {
            add(s, i, 1, 0);
            add(i, t, 1, 0);
            for (int o = 0; o< n; ++o)
            {
                p = cc[o][i];
                if (p < st[o][1])
                {
                    if (p <= st[o][0]) add(i, o+m, 1, dd[o][i]); 
                    else add(i, o+m, 1, dd[o][i]+k*(p - st[o][0]));
                }
            }
        }
        for (int i = 0, p; i< n; ++i)
        {
            add(m+n+i, t, 1, 0);            
            add(m+i, m+n+i, 1, -inf);
            tpm[i] = cnt-1;
            for (int j = 0; j< n; ++j)
            {
                if (i == j) continue;
                p = st[i][1] + ee[i][j];
                if (p < st[j][1])
                {
                    if (p <= st[j][0]) add(m+n+i, m+j, 1, ff[i][j]);
                    else add(m+n+i, m+j, 1, ff[i][j]+k*(p-st[j][0]));
                }
            }
        }
        minCost_maxFlow(s, t);
    }
    return 0;
}



你可能感兴趣的:(最小费用最大流)