zoukankan      html  css  js  c++  java
  • [国家集训队] 航班安排

    对请求拆点建图

    对于一个请求,如果 (0) 时刻可以从 (0) 机场到这里,那么 (S) 向它连边,流量 (infty),费用为 (-w)

    结束时间飞回 (0) 小于时间限制,则向着 (T) 连边,费用为 (-w)

    两两枚举所有请求,如果来得及就同理连边

    最后别忘了限制一下总流量

    跑最小费用最大流即可

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    // Init: init() !!!!!
    // Input: make(u,v,cap,cost)
    // Solver: solve(s,t)
    // Output: ans, cost
    namespace flow {
    const int N = 100005;
    const int M = 1000005;
    const int inf = 1e+12;
    struct Edge {
        int p, c, w, nxt = -1;
    } e[N];
    int s, t, tans, ans, cost, ind, bus[N], qhead = 0, qtail = -1, qu[M],vis[N], dist[N];
    
    void graph_link(int p, int q, int c, int w) {
        e[ind].p = q;
        e[ind].c = c;
        e[ind].w = w;
        e[ind].nxt = bus[p];
        bus[p] = ind;
        ++ind;
    }
    void make(int p, int q, int c, int w) {
        graph_link(p, q, c, w);
        graph_link(q, p, 0, -w);
    }
    int dinic_spfa() {
        qhead = 0;
        qtail = -1;
        memset(vis, 0x00, sizeof vis);
        memset(dist, 0x3f, sizeof dist);
        vis[s] = 1;
        dist[s] = 0;
        qu[++qtail] = s;
        while (qtail >= qhead) {
            int p = qu[qhead++];
            vis[p] = 0;
            for (int i = bus[p]; i != -1; i = e[i].nxt)
                if (dist[e[i].p] > dist[p] + e[i].w && e[i].c > 0) {
                    dist[e[i].p] = dist[p] + e[i].w;
                    if (vis[e[i].p] == 0)
                        vis[e[i].p] = 1, qu[++qtail] = e[i].p;
                }
        }
        return dist[t] < inf;
    }
    int dinic_dfs(int p, int lim) {
        if (p == t)
            return lim;
        vis[p] = 1;
        int ret = 0;
        for (int i = bus[p]; i != -1; i = e[i].nxt) {
            int q = e[i].p;
            if (e[i].c > 0 && dist[q] == dist[p] + e[i].w && vis[q] == 0) {
                int res = dinic_dfs(q, min(lim, e[i].c));
                cost += res * e[i].w;
                e[i].c -= res;
                e[i ^ 1].c += res;
                ret += res;
                lim -= res;
                if (lim == 0)
                    break;
            }
        }
        return ret;
    }
    void solve(int _s,int _t) {
        s=_s; t=_t;
        while (dinic_spfa()) {
            memset(vis, 0x00, sizeof vis);
            ans += dinic_dfs(s, inf);
        }
    }
    void init() {
        memset(bus, 0xff, sizeof bus);
    }
    }
    
    struct query {int a,b,s,t,c;} q[205];
    int N,M,K,T,t[205][205],f[205][205];
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>N>>M>>K>>T;
        flow::init();
        for(int i=1;i<=N;i++) {
            for(int j=1;j<=N;j++) {
                cin>>t[i][j];
            }
        }
        for(int i=1;i<=N;i++) {
            for(int j=1;j<=N;j++) {
                cin>>f[i][j];
            }
        }
        for(int i=1;i<=M;i++) {
            cin>>q[i].a>>q[i].b>>q[i].s>>q[i].t>>q[i].c;
            ++q[i].a;
            ++q[i].b;
            flow::make(i,i+M,1,-q[i].c);
            if(q[i].s >= t[1][q[i].a]) {
                flow::make(2*M+1,i,1e9,f[1][q[i].a]);
            }
            if(T-q[i].t >= t[q[i].b][1]) {
                flow::make(i+M,2*M+2,1e9,f[q[i].b][1]);
            }
        }
        for(int i=1;i<=M;i++) {
            for(int j=1;j<=M;j++) {
                if(q[j].s - q[i].t >= t[q[i].b][q[j].a]) {
                    flow::make(i+M,j,1e9,f[q[i].b][q[j].a]);
                }
            }
        }
        flow::make(2*M+3,2*M+1,K,0);
        flow::solve(2*M+3,2*M+2);
        cout<<-flow::cost;
    }
    
    
  • 相关阅读:
    【模板】Sparse-Table
    UVa 11235 Frequent values
    【模板】树状数组
    UVa 1428 Ping pong
    数学技巧
    UVa 11300 Spreading the Wealth
    UVa 11729 Commando War
    UVa 11292 Dragon of Loowater
    POJ 3627 Bookshelf
    POJ 1056 IMMEDIATE DECODABILITY
  • 原文地址:https://www.cnblogs.com/mollnn/p/12329907.html
Copyright © 2011-2022 走看看