Codeforces 1187 G

G - Gang Up

思路:

每个点按时间拆点建边,然后跑最小费用流

一次走的人不能太多,假设每次走的人为k

(k*k-(k-1)*(k-1))*d <= c+d

k <= 24

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "
";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
int n, m, k, c, d, a[55], x, y;
const int N = 5000 + 10;
const int INF = 0x3f3f3f3f;
struct edge {
    int to, cap, cost, rev;
};
int V;
vector<edge>g[N];
int h[N], dis[N], prevv[N], preve[N];
void add_edge(int u, int v, int cap, int cost) {
    g[u].pb({v, cap, cost, g[v].size()});
    g[v].pb({u, 0, -cost, g[u].size()-1});
}
int min_cost_flow(int s, int t, int f) {
    int res = 0;
    mem(h, 0);
    while(f > 0) {
        priority_queue<pii, vector<pii>, greater<pii> > q;
        mem(dis, 0x3f);
        dis[s] = 0;
        q.push({0, s});
        while(!q.empty()) {
            pii p = q.top();
            q.pop();
            int v = p.se;
            if(dis[v] < p.fi) continue;
            for (int i = 0; i < g[v].size(); ++i) {
                edge &e = g[v][i];
                if(e.cap > 0 && dis[e.to] > dis[v] + e.cost + h[v] - h[e.to]) {
                    dis[e.to] = dis[v] + e.cost + h[v] - h[e.to];
                    prevv[e.to] = v;
                    preve[e.to] = i;
                    q.push({dis[e.to], e.to});
                }
            }
        }
        if(dis[t] == INF) return -1;
        for (int v = 0; v < V; ++v) h[v] += dis[v];
        int d = f;
        for (int v = t; v != s; v = prevv[v]) d = min(d, g[prevv[v]][preve[v]].cap);
        f -= d;
        res += d*h[t];
        for (int v = t; v != s; v = prevv[v]) {
            edge &e = g[prevv[v]][preve[v]];
            e.cap -= d;
            g[v][e.rev].cap += d;
        }
    }
    return res;
}
int s, t;
int main() {
    scanf("%d %d %d %d %d", &n, &m, &k, &c, &d);
    for (int i = 1; i <= k; ++i) scanf("%d", &a[i]);
    s = 0, t = 100*n+1;
    for (int i = 1; i <= k; ++i) add_edge(s, (a[i]-1)*100+1, 1, 0);
    for (int i = 1; i <= 100; ++i) add_edge(i, t, k, 0);
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j < 100; ++j)
            add_edge((i-1)*100+j, (i-1)*100+j+1, k, c);
    }
    for (int i = 1; i <= m; ++i) {
        scanf("%d %d", &x, &y);
        for (int j = 1; j < 100; ++j) {
            for (int k = 1; k <= 24; ++k) {
                add_edge((x-1)*100+j, (y-1)*100+j+1, 1, (k*k-(k-1)*(k-1))*d+c);
                add_edge((y-1)*100+j, (x-1)*100+j+1, 1, (k*k-(k-1)*(k-1))*d+c);
            }
        }
    }
    V = 100*n+2;
    printf("%d
", min_cost_flow(s, t, k));
    return 0;
}
原文地址:https://www.cnblogs.com/widsom/p/11129077.html