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

    题意:先给出每条边的费用,qqq组询问,问当每条边的流量为u/vu/vu/v时,跑到流量为1的最小费用

    思路:对于每次询问,总流量为1,每条边容量为u/v。考虑缩放,同时乘以v,则总流量为v,每条边容量为u,这时算出来的总费用除以v即为答案。 我们可以在询问之前,预处理得到所有增广路的费用,每次进行一次SPFA算法后,就能得到一条增广路的费用,将其记录于vector中。随后从每个增广路费用从小到大开始选取路径进行选取。

    #include <iostream>
    #include <cstring>
    #include <stack>
    #include <vector>
    #include <set>
    #include <map>
    #include <cmath>
    #include <queue>
    #include <sstream>
    #include <iomanip>
    #include <fstream>
    #include <cstdio>
    #include <cstdlib>
    #include <climits>
    #include <deque>
    #include <bitset>
    #include <algorithm>
    using namespace std;
      
    #define PI acos(-1.0)
    #define LL long long
    #define PII pair<int, int>
    #define PLL pair<LL, LL>
    #define mp make_pair
    #define IN freopen("in.txt", "r", stdin)
    #define OUT freopen("out.txt", "wb", stdout)
    #define scan(x) scanf("%d", &x)
    #define scan2(x, y) scanf("%d%d", &x, &y)
    #define scan3(x, y, z) scanf("%d%d%d", &x, &y, &z)
    #define sqr(x) (x) * (x)
    #define pr(x) cout << #x << " = " << x << endl
    #define lc o << 1
    #define rc o << 1 | 1
    #define pl() cout << endl
    //固定流量的最小费用流
    const int MAXN = 100 + 5;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    struct Edge {
        int from, to;
        LL  cap,flow,cost;
    };
    struct MCMF {
        int s, t, n, m;
        LL d[MAXN], p[MAXN], inq[MAXN], a[MAXN];
        vector<int> G[MAXN];
        vector<Edge> edges;
        vector<int> ans;
        void init(int n) {
            this->n = n;
            for (int i = 0; i < n; i++) G[i].clear();
            edges.clear();
            ans.clear();
        }
        void addedge(int from, int to, LL cap, LL cost) {
            edges.push_back((Edge){from, to, cap, 0, cost});
            edges.push_back((Edge){to, from, 0, 0, -cost});
            m = edges.size();
            G[from].push_back(m - 2);
            G[to].push_back(m - 1);
        }
        bool bellman_ford(int s, int t, LL &flow, LL &cost) {
            memset(inq, 0, sizeof(inq));
            for (int i = 0; i < n; i++) d[i] = INF;
            d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;
            queue<int> Q;
            Q.push(s);
            while (!Q.empty()) {
                int u = Q.front(); Q.pop();
                inq[u] = 0;
                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 (!inq[e.to]) {
                            Q.push(e.to);
                            inq[e.to] = 1;
                        }
                    }
                }
            }
            if (d[t] == INF) return false;
            flow += a[t];
            cost += d[t] * a[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;
            }
            ans.push_back(d[t] * a[t]);
            return true;
        }
        void min_cost(int s, int t) {
            LL flow = 0, cost = 0;
            while (bellman_ford(s, t, flow, cost));
        }
    }F;
    int main() {
        int n, m;
        while(~scan2(n, m)){
            F.init(n);
            for (int i = 0; i < m; i++){
                int u,v,w;
                scan3(u,v,w);
                F.addedge(--u,--v,1,w);
            }
            int q;scan(q);
            int S = 0, T = n - 1;
            F.min_cost(S,T);
            while(q--){
                LL u,v;scanf("%lld%lld",&u,&v);
                LL sum=v;
                LL ans=0;
                for(int c:F.ans){
                    LL temp=min(u,sum);
                    ans+=1ll*temp*c;
                    sum-=temp;
                    if(!sum) break;
                }
                if(sum) printf("NaN
    ");
                else{
                    LL cc=__gcd(ans,v);
                    printf("%lld/%lld
    ",ans/cc,v/cc);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    22.渐进式框架的理解
    21、Vue组件间通信6种方式(网上找视频看)
    20、vue中如何使用event对象
    19.vue组件中data为什么必须是一个函数
    18、Vue.js中this.$nextTick()的使用
    17.v-on可以监听多个方法吗
    16.分别简述computed和watch的使用场景
    15. 请说出vue.cli项目中src目录每个文件夹和文件的用法
    13、vue中v-model的应用及使用详解(看链接)
    eclipse编码问题
  • 原文地址:https://www.cnblogs.com/shmilky/p/14089000.html
Copyright © 2011-2022 走看看