• poj2135


    题意:给定一个无向图,要从1点到n点再返回1点,每条边最多走一次,问最短需要走多远。

    分析:最小费用最大流,把题意看成是要找两条无交集的从1到n的路线,使距离和最小。图中的点和边就是网络流图中的点和边。设置一个源,接到1点,设置一个汇,从n点接到汇。为保证无交集,我们把每条边的流量设置为1,而源发出的流量和汇接收的流量均为2。每条边的费用就是该边在原图中的权值。

    注意:有重边,所以要用邻接表。因为是无向图,所以要在加边时,原图中的一条边要变成网络流图中的两条边(如果把反向负权费用边也算上就总共4条边)。

    由于最短路算法是最小费用最大流算法的子算法,所以有些最短路的题可能要用到最小费用最大流。

    View Code
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    
    #define typef int
    #define typec int
    #define maxn 1005
    #define maxm 10005
    #define N maxn + 2
    #define E maxm * 4 + 4
    const typef inff = 0x3f3f3f3f;
    const typec infc = 0x3f3f3f3f;
    
    struct network
    {
        int nv, ne, pnt[E], nxt[E];
        int vis[N], que[N], head[N], pv[N], pe[N];
        typef flow, cap[E];
        typec cost, dis[E], d[N];
        void addedge(int u, int v, typef c, typec w)
        {
            pnt[ne] = v;
            cap[ne] = c;
            dis[ne] = +w;
            nxt[ne] = head[u];
            head[u] = (ne++);
            pnt[ne] = u;
            cap[ne] = 0;
            dis[ne] = -w;
            nxt[ne] = head[v];
            head[v] = (ne++);
        }
        int mincost(int src, int sink)
        {
            int i, k, f, r;
            typef mxf;
            for (flow = 0, cost = 0;;)
            {
                memset(pv, -1, sizeof(pv));
                memset(vis, 0, sizeof(vis));
                for (i = 0; i < nv; ++i)
                    d[i] = infc;
                d[src] = 0;
                pv[src] = src;
                vis[src] = 1;
                for (f = 0, r = 1, que[0] = src; r != f;)
                {
                    i = que[f++];
                    vis[i] = 0;
                    if (N == f)
                        f = 0;
                    for (k = head[i]; k != -1; k = nxt[k])
                        if (cap[k] && dis[k] + d[i] < d[pnt[k]])
                        {
                            d[pnt[k]] = dis[k] + d[i];
                            if (0 == vis[pnt[k]])
                            {
                                vis[pnt[k]] = 1;
                                que[r++] = pnt[k];
                                if (N == r)
                                    r = 0;
                            }
                            pv[pnt[k]] = i;
                            pe[pnt[k]] = k;
                        }
                }
                if (-1 == pv[sink])
                    break;
                for (k = sink, mxf = inff; k != src; k = pv[k])
                    if (cap[pe[k]] < mxf)
                        mxf = cap[pe[k]];
                flow += mxf;
                cost += d[sink] * mxf;
                for (k = sink; k != src; k = pv[k])
                {
                    cap[pe[k]] -= mxf;
                    cap[pe[k] ^ 1] += mxf;
                }
            }
            return cost;
        }
        void build(int v, int e)
        {
            nv = v;
            ne = 0;
            memset(head, -1, sizeof(head));
            int x, y;
            typec w;
            for (int i = 0; i < e; ++i)
            {
                scanf("%d%d%d", &x, &y, &w);
                addedge(x, y, 1, w);// add arc (u->v, f, w)
                addedge(y, x, 1, w);
            }
            addedge(0, 1, 2, 0);
            addedge(v - 2, v - 1, 2, 0);
        }
    } g;
    
    int n, m;
    
    int main()
    {
        //freopen("t.txt", "r", stdin);
        scanf("%d%d", &n, &m);
        g.build(n + 2, m);
        printf("%d\n", g.mincost(0, n + 1));
        return 0;
    }
  • 相关阅读:
    Network Flows(借助ortools)
    【转】一张图看懂IaaS, PaaS和SaaS的区别
    论文中的一些符号 O(big-Oh) Ω(big-omega) Θ(big-theta)
    最大流问题
    4 Mininet测量路径的损耗率
    3 Mininet命令延伸实验拓展
    2 Mininet可视化应用
    快速定位问题
    软中断与软中断的排查
    系统出现大量不可中断进程与僵尸进程
  • 原文地址:https://www.cnblogs.com/rainydays/p/2577386.html
Copyright © 2020-2023  润新知