• 网络流24题(11)航空路线问题(最大费用最大流)


    思路:

    1. 题目最终可以抽象为:最长不相交路径问题,两条从 s 到 t 的不相交路径的最大长度;

    2. 把每个点分成 <i, X> <i, Y> 两点,引弧,容量为 1,费用为 1,特殊的:s, t 容量设置为 2,因为可以重复选择;

    3. 对于 i, j 存在路径且 i < j 则 <i, Y> 向 <j, X> 引弧,容量为 1,费用为 0. 特殊的如果 i = s, j = t,容量设置为 2;

    4. 求上述网络的最大费用最大流,把费用设置为负数,即可求最小费用最大流。结果 - 2 即是输出结果。

    #include <iostream>
    #include <queue>
    #include <vector>
    #include <map>
    #include <string>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 1010;
    const int INFS = 0x3FFFFFFF;
    
    struct edge {
        int from, to, cap, flow, cost;
        edge(int _from, int _to, int _cap, int _flow, int _cost)
            : from(_from), to(_to), cap(_cap), flow(_flow), cost(_cost) {}
    };
    
    class MCMF {
    public:
        void initdata(int n) {
            this->n = n;
            edges.clear();
            for (int i = 0; i < n; i++)
                G[i].clear();
        }
        void addedge(int u, int v, int cap, int cost) {
            edges.push_back(edge(u, v, cap, 0, cost));
            edges.push_back(edge(v, u, 0, 0, -cost));
            G[u].push_back(edges.size() - 2);
            G[v].push_back(edges.size() - 1);
        }
        bool SPFA() {
            for (int i = 0; i < n; i++)
                d[i] = INFS, vis[i] = false;
            queue<int> Q;
            Q.push(s);
            d[s] = 0, vis[s] = true, p[s] = 0, a[s] = INFS;
            while (!Q.empty()) {
                int u = Q.front(); Q.pop();
                vis[u] = false;
                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;
                        p[e.to] = G[u][i];
                        a[e.to] = min(a[u], e.cap - e.flow);
                        if (!vis[e.to]) { vis[e.to] = true; Q.push(e.to); }
                    }
                }
            }
            return d[t] != INFS;
        }
        void augment(int& flow, int& cost) {
            flow += a[t];
            cost += a[t] * d[t];
            int u = t;
            while (u != s) {
                edges[p[u]].flow += a[t];
                edges[p[u]^1].flow -= a[t];
                u = edges[p[u]].from;
            }
        }
        int mincost(int s, int t) {
            this->s = s, this->t = t;
            int flow = 0, cost = 0;
            while (SPFA()) {
                augment(flow, cost);
            }
            return cost;
        }
        bool isvalid(int delta) {
            if (edges[G[s][0]].flow == 2)
                return true;
            return false;
        }
        void getpath(int x, int delta, vector<int>& v) {
            for (int i = 0; i < G[x].size(); i++) {
                edge& e = edges[G[x][i]];
                if (e.flow == 1 && !vis[e.to]) {
                    vis[e.to] = true;
                    v.push_back(e.to);
                    getpath(e.to + delta, delta, v);
                    break;
                }
            }
        }
        void getans(int delta, vector<int>& v1, vector<int>& v2) {
            memset(vis, false, sizeof(vis));
            v1.push_back(s); 
            v2.push_back(s);
            getpath(s + delta, delta, v1);
            getpath(s + delta, delta, v2);
        }
    private:
        vector<edge> edges;
        vector<int> G[MAXN];
        int n, s, t, d[MAXN], p[MAXN], a[MAXN];
        bool vis[MAXN];
    };
    
    MCMF mcmf;
    string city[MAXN];
    map<string, int> my;
    
    int main() {
        int n, v;
        cin >> n >> v;
        int s = 1, t = n + n;
        mcmf.initdata(t + 1);
        for (int i = 1; i <= n; i++) {
            cin >> city[i];
            my[city[i]] = i;
            if (i == 1 || i == n)
                mcmf.addedge(i, i+n, 2, -1);
            else
                mcmf.addedge(i, i+n, 1, -1);
        }
        for (int i = 0; i < v; i++) {
            string a, b;
            cin >> a >> b;
            int k1 = min(my[a], my[b]);
            int k2 = max(my[a], my[b]);
            if (k1 == 1 && k2 == n)
                mcmf.addedge(k1+n, k2, 2, 0);
            else
                mcmf.addedge(k1+n, k2, 1, 0);
        }
        int cost = mcmf.mincost(s, t);
        if (mcmf.isvalid(n)) {
            cost = -cost-2;
            cout << cost << endl;
            vector<int> v1;
            vector<int> v2;
            mcmf.getans(n, v1, v2);
            for (int i = 0; i < v1.size(); i++)
                cout << city[v1[i]] << endl;
            for (int i = v2.size() - 1; i >= 0; i--)
                cout << city[v2[i]] << endl;
        } else {
            cout << "No Solution!" << endl;
        }
        return 0;
    }
  • 相关阅读:
    nginx日志
    silverlight 双击事件
    Silverlight button 图片切换样式
    Caliburn.Micro学习笔记(一)----引导类和命名匹配规则
    关闭Outlook时最小化 dll
    wpf键盘记录器
    WPF之TreeList的实现方法(一)
    精典算法之详解 河内之塔
    精典算法之二分查找法
    指针数组和数组指针
  • 原文地址:https://www.cnblogs.com/kedebug/p/3045736.html
Copyright © 2020-2023  润新知