POJ 2135 Farm Tour 最小费用流

有N的点,1是farmer john的家  n是barn要求从1开始走到n再走回来,不许走重复的路线,使之能从1走到n在走回来,且要经过每个点。费用流的模型。

建立一个新源点容量为2,费用为0连向点1,然后n连向一个汇点,原来的图是无向图,所以要加2个有向边求解。之后就是费用流了

题目保证可以走回来的,这样加边的原因是有向边是在网络中有一定的关系的,有流量从A到B的流过,那么在最终的网络流中一定不可能从B到A流回来

#include <iostream>

#include <cstring>

#include <cstdio>

#include <queue>

#include <algorithm>

using namespace std;



 



class mincost

{

private:

    const static int V = 1001;

    const static int E = 1000001;

    const static int INF = 0x7ffffff;



    struct Edge

    {

        int v, cap, cost;

        Edge *next;

    } pool[E], *g[V], *pp, *pree[V];

    int T, S, dis[V], pre[V];

    int n, m;

    void SPFA();

    inline void addedge(int i, int j, int cap, int cost);

public:

    bool initialize();

    void mincost_maxflow();

};



void mincost::mincost_maxflow()

{

    int flow = 0;

    while (true)

    {

        SPFA();

        if (dis[T] == INF)

            break;

        int minn = INF;

        for (int i = T; i != S; i = pre[i])

            minn = min(minn, pree[i]->cap);

        for (int i = T; i != S; i = pre[i])

        {

            pree[i]->cap -= minn;

            pool[(pree[i] - pool)^0x1].cap += minn;

            flow += minn * pree[i]->cost;

        }

    }

    printf("%d\n", flow);

}



void mincost::SPFA()

{

    bool vst[V] = {false};

    int cirq[V];

    int tail = 0, u;

    fill(dis, dis + T + 1, 0x7ffffff);

    cirq[0] = S;

    vst[S] = 1;

    dis[S] = 0;

    for (int j = 0; j <= tail; j++)

    {

        int v = cirq[j % n];

        for (Edge *i = g[v]; i != NULL; i = i->next)

        {

            if (!i->cap)

                continue;

            u = i->v;

            if (i->cost + dis[v] < dis[u])

            {

                dis[u] = i->cost + dis[v];

                pree[u] = i;

                pre[u] = v;

                if (!vst[u])

                {

                    tail++;

                    cirq[tail % n] = u;

                    vst[u] = true;

                }

            }

        }

        vst[v] = false;

    }

}



void mincost::addedge(int i, int j, int cap, int cost)

{

    pp->cap = cap;

    pp->v = j;

    pp->cost = cost;

    pp->next = g[i];

    g[i] = pp++;

}



bool mincost::initialize()

{

    if (scanf("%d %d", &n, &m) != 2)

        return false;

    memset(g, 0, sizeof (g));

    pp = pool;

    S = 0, T = n + 1;

    int v, u, c;

    addedge(S, 1, 2, 0);

    addedge(1, S, 0, 0);

    addedge(n, T, 2, 0);

    addedge(T, n, 0, 0);

    n += 2;

    for (int i = 0; i < m; i++)

    {

        scanf("%d %d %d", &v, &u, &c);

        addedge(v, u, 1, c);

        addedge(u, v, 0, -c);

        addedge(u, v, 1, c);

        addedge(v, u, 0, -c);

    }

    return true;

}

mincost g;



int main()

{

    while (g.initialize())

        g.mincost_maxflow();

    return 0;

}

你可能感兴趣的:(poj)