• SGU 185.Two shortest (最小费用最大流)


    时间限制:0.25s

    空间限制:4M

    题意:

           在n(n<=400)个点的图中,找到并输出两条不想交的最短路。不存在输出“No sulotion”;


    Solution:

                最小费用最大流

                建图与poj 2135 一样,添加S到1的流量为2权为0,n到T的流量为2权为0的边,其它边的流量为1,权为路径长度.

                但是这道题麻烦不在要输出最短路,而在仅仅4M的内存上。

                由于只有4M,我们最多存上400*400条边.但是图却是一个无向图,朴素的想法是存上400*400*2条边,但是这里内存不够.

                所以我们首先要确定记录一条边我们是否使用过,如果使用了使用的是那个方向.

                相应的在找到增广路后,把正向反向边的流量改变,把反向边的费用变成负值.

                最后按照我们标记过的边dfs,并输出就好了.

                总的来说是一道足以加深对最小费用最大流的理解的不错的题!

    参考代码:

    /*
           最小费用最大流算法:
           思路:
           以费用为权做最短路算法。
    */
    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <cmath>
    using namespace std;
    const int INF = 409, Maxn = 0x3f3f3f3f;
    
    struct node {
        int u, v, t, c, next;
    } edge[INF * INF];
    int head[INF], nCnt = 1;
    int G[INF][INF];
    void addEdge (int u, int v, int traffic, int cost) {
        edge[++nCnt].v = v, edge[nCnt].u = u, edge[nCnt].t = traffic, edge[nCnt].c = cost;
        edge[nCnt].next = head[u], head[u] = nCnt;
        edge[++nCnt].v = u, edge[nCnt].u = v, edge[nCnt].t = traffic, edge[nCnt].c = cost;
        edge[nCnt].next = head[v], head[v] = nCnt;
    }
    int max_flow, min_cost;
    int n, m, SS, ST, S, T, min_dis = Maxn;
    int SPFA() {
        queue<int> ql;
        int vis[INF] = {0}, dis[INF], pre[INF] = {0};
        ql.push (SS);
        memset (dis, 0x3f, sizeof dis);
        vis[SS] = 1, dis[SS] = 0;
        while (!ql.empty() ) {
            int x = ql.front(); ql.pop();
            for (int i = head[x]; i != 0; i = edge[i].next) {
                if (edge[i].t == 0) continue;
                int v = edge[i].v, c = edge[i].c;
                if (dis[v] > dis[x] + c) {
                    dis[v] = dis[x] + c;
                    pre[v] = i;
                    if (!vis[v])
                        ql.push (v), vis[v] = 1;
                }
            }
            vis[x] = 0;
        }
        min_dis = min (min_dis, dis[ST]);
        if (dis[ST] == Maxn) return 0;
        else {
            min_cost += dis[ST];
            int k = pre[ST];
            int cur_flow = Maxn;
            while (k) {
                if (cur_flow > edge[k].t) cur_flow = edge[k].t;
                G[edge[k].u][edge[k].v] = G[edge[k].v][edge[k].u] = 1 ^ G[edge[k].v][edge[k].u];
                edge[k].t = edge[k ^ 1].t, edge[k].c = abs (edge[k].c);
                edge[k ^ 1].t = 0, edge[k ^ 1].c = -abs (edge[k ^ 1].c);
                k = pre[edge[k].u];
            }
            max_flow += cur_flow;
            k = pre[ST];
            while (k) {
                edge[k].t -= cur_flow, edge[k ^ 1].t += cur_flow;
                k = pre[edge[k].u];
            }
            return 1;
        }
    }
    void dfs (int x) {
        for (int i = head[x]; i != 0; i = edge[i].next) {
            if (G[x][edge[i].v] && edge[i].t > 0 && edge[i].v < T) {
                edge[i].t = 0;
                dfs (edge[i].v);
                break;
            }
        }
        if (x == S) printf ("%d", x);
        else
            printf (" %d", x);
    }
    int MCMF() {
        while (SPFA() );
        if (max_flow == 2 && min_cost == 2 * min_dis) {
            dfs (T);
            putchar (10);
            dfs (T);
        }
        else
            puts ("No solution");
    }
    void build() {
        scanf ("%d %d", &n, &m);
        int x, y, z;
        for (int i = 1; i <= m; i++) {
            scanf ("%d %d %d", &x, &y, &z);
            addEdge (x, y, 1, z);
        }
        S = 1, T = n;
        SS = n + 1, ST = n + 2;
        addEdge (SS, S, 2, 0), addEdge (T, ST, 2, 0);
    }
    int main() {
        build();
        MCMF();
        return 0;
    }
    View Code
  • 相关阅读:
    简单SSO(Single signon)的另类实现方式,钩子技术
    URL
    [恢]hdu 1287
    [恢]hdu 1220
    [恢]hdu 1015
    [恢]hdu 2095
    [恢]hdu 1862
    HDOJ 300!
    [恢]hdu 1029
    [恢]hdu 1016
  • 原文地址:https://www.cnblogs.com/keam37/p/3982552.html
Copyright © 2020-2023  润新知