[2020HDU multi-school] The second session 1005 (HDU6767) New Equipments-cost flow

Topic link

Topic

Gives nnn workers andmmm pieces of equipment, the equipment number is1, 2, 3... m 1, 2, 3... m1,2,. 3 . . . M .
For workersiii , he has three parametersai, bi, ci a_i, b_i, c_iai,bi,ci, When the worker is equipped with jjFor j equipment, it costsai ∗ j 2 + bi ∗ j + ci a_i * j ^ 2+ b_i * j + c_iaij2+bij+cicost of. Think of
it as kkWhen k workers are equipped with equipment, what is the minimum cost?
To allkkAll cases of k need to be output

analysis

Expense flow
Link each employee with the source point, and take nn near the minimum value of each employee’s quadratic function curven points, connected to the employee, all the points on the quadratic function curve are connected to the meeting point, the line connecting the employee to the quadratic function needs to set the cost, other line costs are0 00 , the flow of all lines is1 11

Output the cost of each spfa process

AC code

#include <bits/stdc++.h>

using namespace std;

#define ll long long

const ll maxn = 3000;
const ll INF = 0x3f3f3f3f3f3f3f3f;

bool flag;

struct Edge {
    
    
    ll from, to, cap, flow, cost;

    Edge(ll u, ll v, ll c, ll f, ll cc)
            : from(u), to(v), cap(c), flow(f), cost(cc) {
    
    }
};

struct MCMF {
    
    
    ll n, m;
    vector<Edge> edges;
    vector<ll> G[maxn];
    ll inq[maxn];  //是否在队列中
    ll d[maxn];    //bellmanford
    ll p[maxn];    //上一条弧
    ll a[maxn];    //可改进量
    void init(ll nn) {
    
    
        this->n = nn;
        for (ll i = 0; i <= n; ++i) G[i].clear();
        edges.clear();
    }

    void addEdge(ll from, ll to, ll cap, ll cost) {
    
    
        edges.emplace_back(Edge(from, to, cap, 0, cost));
        edges.emplace_back(Edge(to, from, 0, 0, -cost));
        m = (ll) (edges.size());
        G[from].emplace_back(m - 2);
        G[to].emplace_back(m - 1);
    }

    bool spfa(ll s, ll t, ll &flow, ll &cost) {
    
    
        for (ll i = 1; i <= n; ++i) d[i] = INF;
        memset(inq, 0, sizeof(inq));
        d[s] = 0;
        inq[s] = 1;
        p[s] = 0;
        queue<ll> q;
        a[s] = INF;
        q.push(s);
        while (!q.empty()) {
    
    
            ll u = q.front();
            q.pop();
            inq[u] = 0;
            for (ll i = 0; i < (ll) (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 += (ll) d[t] * (ll) a[t];
        cout << (flag ? " " : "") << cost;
        flag = true;
        for (ll u = t; u != s; u = edges[p[u]].from) {
    
    
            edges[p[u]].flow += a[t];
            edges[p[u] ^ 1].flow -= a[t];
        }
        return true;
    }

    ll MincostMaxflow(ll s, ll t, ll &cost) {
    
    
        ll flow = 0;
        cost = 0;
        while (spfa(s, t, flow, cost));
        return flow;
    }
} mcmf;

struct Node {
    
    
    ll a, b, c;
    ll l, r;

    ll cal(ll x) {
    
    
        return a * x * x + b * x + c;
    }

    void make(ll n, ll m) {
    
    
        ll mid = -b / 2 / a;
        l = mid - n / 2 - 1;
        r = mid + n / 2 + 1;
        l = max(1ll, l);
        r = min(m, r);
        if (r == m) {
    
    
            l = r - n - 2;
        } else if (l == 1) {
    
    
            r = l + n + 2;
        }
    }
} node[60];

void solve() {
    
    
    ll T;
    cin >> T;
    for (ll ts = 0; ts < T; ++ts) {
    
    
        flag = false;
        unordered_map<ll, ll> trans;
        ll n, m;
        cin >> n >> m;
        ll ind = 51;
        for (ll i = 1; i <= n; ++i) {
    
    
            cin >> node[i].a >> node[i].b >> node[i].c;
            node[i].make(n, m);
            ll l = node[i].l;
            ll r = node[i].r;
            assert(r - l < 60);
            for (ll j = l; j <= r; ++j) {
    
    
                if (trans.count(j)) continue;
                trans.insert({
    
    j, ind++});
            }
        }
        ll source = ind + 10, target = ind + 11;
        mcmf.init(target + 10);
#ifdef ACM_LOCAL
        cerr << target + 10 << endl;
#endif
        for (auto &item : trans)
            mcmf.addEdge(item.second, target, 1, 0);
        for (ll i = 1; i <= n; ++i) {
    
    
            mcmf.addEdge(source, i, 1, 0);
            for (ll j = node[i].l; j <= node[i].r; ++j) {
    
    
                mcmf.addEdge(i, trans[j], 1, node[i].cal(j));
            }
        }
        ll cost;
        mcmf.MincostMaxflow(source, target, cost);
        cout << endl;
    }
}

signed main() {
    
    
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
#ifdef ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug;
    while (cin >> acm_local_for_debug) {
    
    
        if (acm_local_for_debug == '$') exit(0);
        cin.putback(acm_local_for_debug);
        if (test_index_for_debug > 20) {
    
    
            throw runtime_error("Check the stdin!!!");
        }
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    }
#else
    solve();
#endif
    return 0;
}

Guess you like

Origin blog.csdn.net/m0_43448982/article/details/107555668
Recommended