• POJ 2135 /// 最小费用流最大流 非负花费 BellmanFord模板


    题目大意:

    给定一个n个点m条边的无向图

    求从点1去点n再从点n回点1的不重叠(同一条边不能走两次)的最短路

    挑战P239

    求去和回的两条最短路很难保证不重叠

    直接当做是由1去n的两条不重叠的最短路

    这样就变成了由1去n流量为2的最小费用流

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    using namespace std;
    const int N=1005;
    int n,m;
    struct EDGE { int v,w,c,r; };
    vector <EDGE> E[N];
    void addE(int u,int v,int w,int c) {
        E[u].push_back((EDGE){v,w,c,E[v].size()});
        E[v].push_back((EDGE){u,0,-c,E[u].size()-1});
    }
    int dis[N], pv[N] ,pe[N];
    int minCFlow(int s,int t,int f) {
        int res=0;
        while(f>0) {
            /// Bellman-Ford求s到t最短路
            memset(dis,INF,sizeof(dis));
            memset(pv,0,sizeof(pv));
            dis[s]=0;
            bool upD=1;
            while(upD) {
                upD=0;
                for(int i=0;i<=n;i++) { // 通过i点
                    if(dis[i]==INF) continue;
                    for(int j=0;j<E[i].size();j++) { // 更新E[i][j]点的最短路
                        EDGE& e=E[i][j];
                        if(e.w>0 && dis[e.v]>dis[i]+e.c) { // 边容量>0才能走
                            dis[e.v]=dis[i]+e.c; // 找到更短的路 更新
                            pv[e.v]=i, pe[e.v]=j; // 记录前驱点及边 便于通过e.v找到i点
                            upD=1;
                        }
                    }
                }
            }
            if(dis[t]==INF) return -1; // s不能到t 不能增广
    
            int d=f; // 找到本轮实际能够流出的流量(即实际用掉的容量)
            for(int i=t;pv[i];i=pv[i])
                d=min(d,E[pv[i]][pe[i]].w);
            f-=d; // 容量消耗
            res+=d*dis[t]; // 计算本轮花费
            for(int i=t;pv[i];i=pv[i]) {
                EDGE& e=E[pv[i]][pe[i]];
                e.w-=d;
                E[i][e.r].w+=d;
            } // 更新边的容量
        }
        return res;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m)) {
            int s=1, t=n;
            for(int i=0;i<m;i++) {
                int u,v,c; scanf("%d%d%d",&u,&v,&c);
                addE(u,v,1,c); addE(v,u,1,c);
                // 建立u到v容量大小为1费用为c的边
            }
            printf("%d
    ",minCFlow(s,t,2));
            // 求s到t传输大小为2(即最大容量为2)的最小费用流
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    Linux学习笔记之Linux Centos关闭防火墙
    ELK学习笔记之Logstash详解
    ELK学习笔记之ElasticSearch的索引详解
    C语言拼接字符串 -- 使用strcat()函数
    linux 中的 open() read() write() close() 函数
    stderr 和stdout
    ubuntu14.04 放开串口权限
    ubuntu14.04 安装 openssh-server
    串口接线
    ubuntu + usb转RS232驱动
  • 原文地址:https://www.cnblogs.com/zquzjx/p/10153650.html
Copyright © 2020-2023  润新知