[Bzoj1061][Noi2008]志愿者招募(费用流)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1061
一开始疯狂想dp,然后队友走过来瞄一眼就告诉我像费用流,菜的真实,jpg。
一种比较经典的建图方法:
源点连第一天,流量inf,费用0。
第n天连汇点,流量inf,费用0。
第i天连第i+1天,流量inf-a[i](需要的人数),费用0。(限制流量)
第i种可以选择的人,将Si+1天连Ti天,流量inf,费用Ci。(花钱购买流量)
菜的真实.jpg
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 2e6 + 10; 5 const int inf = 1e7 + 10; 6 struct node { 7 int s, e, w, cost, next; 8 }edge[maxn]; 9 int head[maxn], len; 10 void init() { 11 memset(head, -1, sizeof(head)); 12 len = 0; 13 } 14 void add(int s, int e, int w, int cost) { 15 edge[len].s = s; 16 edge[len].e = e; 17 edge[len].w = w; 18 edge[len].cost = cost; 19 edge[len].next = head[s]; 20 head[s] = len++; 21 } 22 void insert(int s, int e, int w, int cost) { 23 add(s, e, w, cost); 24 add(e, s, 0, -cost); 25 } 26 int pre[maxn], dis[maxn], vis[maxn]; 27 bool spfa(int s, int e) { 28 memset(dis, 0x7f, sizeof(dis)); 29 memset(vis, 0, sizeof(vis)); 30 memset(pre, -1, sizeof(pre)); 31 queue<int>q; 32 q.push(s); 33 vis[s] = 1, dis[s] = 0; 34 while (!q.empty()) { 35 int x = q.front(); 36 q.pop(); 37 vis[x] = 0; 38 for (int i = head[x]; i != -1; i = edge[i].next) { 39 int y = edge[i].e; 40 if (edge[i].w&&dis[y] > dis[x] + edge[i].cost) { 41 dis[y] = dis[x] + edge[i].cost; 42 pre[y] = i; 43 if (vis[y] == 0) { 44 vis[y] = 1; 45 q.push(y); 46 } 47 } 48 } 49 } 50 return pre[e] != -1; 51 } 52 int MCMF(int s, int e) { 53 int maxans = 0, minans = 0; 54 while (spfa(s, e)) { 55 int f = inf; 56 for (int i = pre[e]; i != -1; i = pre[edge[i].s]) 57 f = min(f, edge[i].w); 58 maxans += f; 59 minans += dis[e] * f; 60 for (int i = pre[e]; i != -1; i = pre[edge[i].s]) { 61 edge[i].w -= f; 62 edge[i ^ 1].w += f; 63 } 64 } 65 return minans; 66 } 67 int main() { 68 int n, m; 69 int x, l, r, cost; 70 scanf("%d%d", &n, &m); 71 init(); 72 int w = inf; 73 for (int i = 1; i <= n; i++) { 74 scanf("%d", &x); 75 add(i, i + 1, w - x, 0); 76 add(i + 1, i, 0, 0); 77 } 78 insert(0, 1, w, 0); 79 insert(n + 1, n + 2, w, 0); 80 for (int i = 1; i <= m; i++) { 81 scanf("%d%d%d", &l, &r, &cost); 82 insert(l, r + 1, w, cost); 83 } 84 printf("%d\n", MCMF(0, n + 2)); 85 return 0; 86 }