zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第一场)H-Minimum-cost Flow(最小费用流)

    题目链接

    题目大意:初始给定一个(n)个点,(m)条边,费用全部确定的网络。要求对于接下来的(k)次询问,每次都给定所有边的容量为一个分数(frac{u}{v})。要求对于每一个询问计算从点(1)到点(n)跑大小为(1)的流的最小花费。
    大致思路:因为我们事先知道了所有边的费用,并且后续所有边的最大容量全部相同。那么初始建图的时候所有边的最大容量都设置为(1),这样我们只需要跑一边最小费用最大流,并且记录每一次的增广路径的花费(由于容量为(1),所以最少花费就是最短路的距离)。然后对于每一次询问我们进行分析:由于容量给定的是一个分数,所以我们先将所有边的容量扩大至(v)倍,那么所有边的最大容量就变成了(u)。所以现在我们要大小为(v)的流,最后得出的花费除以(v)就是最终所求的答案。由于所有的最大容量都为(u),所以每一次的增广所增加的流量都为(u)。最后一次把剩余的流量补全即可。如果最大流无法达到(v),就输出(NaN)。具体看代码实现。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    class MinCostFlow {
    public:
        struct Result {
            int flow, cost;
        };
    
        MinCostFlow(int n, int m = 0) : visited(n), head(n, -1), dist(n), prev(n) ,flow(n), preu(n){
            edges.reserve(m << 1);
        }
    
        void add_edge(int u, int v, int capacity, int cost) {
            internal_add_edge(u, v, capacity, cost);
            internal_add_edge(v, u, 0, -cost);
        }
    
        bool spfa(int src, int dst) {
            const int infdist = std::numeric_limits<int>::max();
            std::fill(dist.begin(), dist.end(), infdist);
            std::fill(flow.begin(), flow.end(), infdist);
            dist[src] = 0;
            std::queue<int> queue;
            queue.push(src);
            while (!queue.empty()) {
                int u = queue.front();
                queue.pop();
                visited[u] = false;
                for (int iter = head[u]; ~iter;) {
                    int v = edges[iter].v;
                    if (edges[iter].rest && dist[u] + edges[iter].cost < dist[v]) {
                        dist[v] = dist[u] + edges[iter].cost;//费用增广路的最短路
                        prev[v] = iter;//上一边
                        preu[v] = u;//前驱点
                        flow[v] = min(flow[u],edges[iter].rest);//增广的瓶颈流量
                        if (!visited[v]) {
                            visited[v] = true;
                            queue.push(v);
                        }
                    }
                    iter = edges[iter].next;
                }
            }
            return dist[dst]!=infdist;
        }
        vector<int> ans;
        Result MCMF(int src,int dst){
            int maxflow=0,mincost=0;
            while(spfa(src,dst)){
                int v=dst;
                ans.push_back(dist[dst]);
                maxflow+=flow[dst];
                mincost+=flow[dst]*dist[dst];
                while(v!=src){
                    edges[prev[v]].rest-=flow[dst];
                    edges[prev[v]^1].rest+=flow[dst];
                    v=preu[v];
                }
            }
            return Result{maxflow,mincost};
        }
    
    private:
        struct Edge {
            int v, next, rest, cost;//终点,下条边,容量,花费
        };
    
        void internal_add_edge(int u, int v, int capacity, int cost) {
            edges.push_back(Edge{v, head[u], capacity, cost});
            head[u] = edges.size() - 1;
        }
    
        std::vector<bool> visited;
        std::vector<int> head, dist, prev, flow, preu;
        std::vector<Edge> edges;
    };
    
    int main(){
        int n,m;
        while(cin>>n>>m){
            MinCostFlow net(n,m);
            for(int i=0,a,b,c;i<m;i++){
                cin>>a>>b>>c;
                net.add_edge(a-1,b-1,1,c);
            }
            auto res=net.MCMF(0,n-1);
            int q;
            cin>>q;
            while(q--){
                int u,v;
                scanf("%d%d",&u,&v);
                if(u==0)puts("NaN");
                else{
                    ll fz=0,fm=v;
                    for(int an : net.ans){
                        if(v>u)fz+=1ll*an*u,v-=u;
                        else {fz+=1ll*an*v,v=0;break;}
                    }
                    if(v)puts("NaN");
                    else{
                        ll gd=__gcd(fz,fm);
                        printf("%lld/%lld
    ",fz/gd,fm/gd);
                    }
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    模仿jquery的一些实现
    使按钮失效的方法
    类似jquery的一个demo
    oracle 集合变量以及自定义异常的用法
    java的for循环问题的解决,以及安卓中ListView插入数据的问题
    Spring AOP基于xml配置实例
    plsql 的循环之 goto
    Spring AOP报错
    补全aaz288 可能有问题的过程 P_COMPL_AAZ288
    Spring注解配置
  • 原文地址:https://www.cnblogs.com/charles1999/p/13346591.html
Copyright © 2011-2022 走看看