• poj 2135 最小费用最大流初步


      这个题的意思是农夫约翰要呆人参观他的农场, 刚开始从1开始走, 走到N后又返回1点, 两次不能走相同的路, 问农夫约翰走的最短的路是多少??
      我们可以用最小MCMF来解决这个问题, 对于图中的每一条边, 我们建立了两条流量为1, 费用为边权的边, 再增加一个源点和一个汇点, 源点指向1, 流量为2,费用为0, N指向汇点, 流量为2费用为0, 然后求出最小费用即可, 代码如下:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    #include <vector>
    
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const int maxn = 1000+10;
    
    int n;     //n个顶点
    struct Edge{ int from, to, cap, flow, cost; };
    vector<Edge> edges;
    vector<int> G[maxn];
    int inque[maxn];   //SPFA 需要用到
    int d[maxn];       //当前点到源点的最短路
    int p[maxn];       //连接当前点的弧
    int a[maxn];       //可改进量
    
    void init()
    {
        for(int i=0; i<=n; i++) G[i].clear();
        edges.clear();
    }
    
    void add_edge(int from, int to, int cap, int cost)
    {
        edges.push_back((Edge){from, to, cap, 0, cost});
        edges.push_back((Edge){to, from, 0, 0, -cost});
        int m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    
    bool spfa(int s, int t, int &flow, long long &cost)
    {
        for(int i=0; i<=n; i++) d[i] = inf;
        memset(inque, 0, sizeof(inque));
        d[s] = 0; inque[s]=1; p[s] = 0; a[s] = inf;
        queue<int> que;
        que.push(s);
        while(!que.empty()){
            int u = que.front(); que.pop();
            inque[u] = 0;
            for(int i=0; i<G[u].size(); i++){
                Edge e = edges[G[u][i]];
                if(e.cap>e.flow && d[e.to]>d[u]+e.cost){
                    d[e.to] = d[u] + e.cost;
                    if(!inque[e.to]) que.push(e.to), inque[e.to]=1;
                    p[e.to] = G[u][i];    //e.to连接的边是G[u][i]
                    a[e.to] = min(a[u], e.cap-e.flow);   //更新可改进量
                }
            }
        }
        if(d[t] == inf) return false;
        flow += a[t];
        cost += (long long)a[t] * (long long)d[t];
        for(int u=t; u!=s; u=edges[p[u]].from)
        {
            edges[p[u]].flow += a[t];
            edges[p[u]^1].flow -= a[t];
        }
        return true;
    }
    int MCMF(int s, int t, long long &cost)
    {
        int flow = 0; cost = 0;
        while(spfa(s, t, flow, cost));
        return flow;
    }
    
    int N, M;
    
    int main()
    {
        scanf("%d%d", &N, &M);
        n = N+2;
        init();
        for(int i=0; i<M; i++)
        {
            int u, v, c;
            scanf("%d%d%d", &u, &v, &c);
            add_edge(u, v, 1, c);
            add_edge(v, u, 1, c);
        }
        add_edge(0, 1, 2, 0);
        add_edge(N, N+1, 2, 0);
        long long cost;
        MCMF(0, N+1, cost);
        printf("%lld
    ", cost);
        return 0;
    }
  • 相关阅读:
    2017第17周四当前工作中困境与挑战思考
    2017第17周三
    2017第17周二
    最小可行产品
    《穷查理宝典》中三条最重要的学习方法
    机场打车有感
    2017第15周五
    2017第15周四
    三条经济学原理帮你做出正确的选择
    Mac通过安装Go2Shell实现“在当前目录打开iTerm2”
  • 原文地址:https://www.cnblogs.com/xingxing1024/p/5275296.html
Copyright © 2020-2023  润新知