差不多就是个二分图带权匹配?(我还是敲费用流吧)
每个点向着自己能到的学校连边,费用按题意设定
跑最小费用最大流即可
#include <bits/stdc++.h> using namespace std; // 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+9; 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); } } const int N = 505; int n,m[N],a[N],b[N],k[N]; int id_school(int i) { return i+2; } int id_num(int i) { return i+n+2; } void make(int u,int v,int w,int c) { flow::make(u,v,w,c); } signed main() { cin>>n; flow::init(); for(int i=1;i<=n;i++) cin>>m[i]>>a[i]>>b[i]>>k[i]; for(int i=1;i<=n;i++) { make(1,id_school(i),1,0); make(id_num(i),2,1,0); for(int j=a[i];j<=b[i];j++) { make(id_school(i),id_num(j),1,k[i]*abs(m[i]-j)); } } flow::solve(1,2); if(flow::ans!=n) puts("NIE"); else cout<<flow::cost; }
来源:https://www.cnblogs.com/mollnn/p/12293829.html