[费用流]LOJ#6079. 「2017 山东一轮集训 Day7」养猫
2017-10-12 18:29
477 查看
Description
你养了一只猫,为了让它快乐地成长,你需要合理地安排它每天的作息时间。假设一天分为n个时刻,猫在每个时刻要么是吃东西,要么是睡觉。在第i个时刻,假如猫是去吃东西,那么它能获得愉悦值ei,假如是去睡觉,那么能获得的愉悦值为si 。猫要成长,不仅仅需要快乐,还需要健康的作息。经过研究,对于每一个连续的长度为k的作息区间,即所有的时刻区间[i,i+k−1],1≤i≤n−k+1,猫都要至少有ms 的时刻用来睡觉,me的时刻用来吃东西,这样猫才能健康成长。
现在你想合理地安排一天中的这n个时刻,使得猫在能健康成长的前提下,获得尽量多的愉悦值。
Solution
**#include <bits/stdc++.h> using namespace std; const int INF = 1 << 30; const int N = 1010; typedef long long ll; inline char get(void) { static char buf[100000], *S = buf, *T = buf; if (S == T) { T = (S = buf) + fread(buf, 1, 100000, stdin); if (S == T) return EOF; } return *S++; } inline void read(int &x) { static char c; x = 0; for (c = get(); c < '0' || c > '9'; c = get()); for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0'; } struct edge { int to, next; int cap, cost; edge (int t = 0, int n = 0, int c = 0, int co = 0):to(t), next(n), cap(c), cost(co) {} }; edge G[N << 3]; int head ; ll dist ; int vis , pre ; int s , e ; int ans ; int Gcnt, n, k, ms, me; ll Ans; queue<int> Q; inline void AddEdge(int from, int to, int cap, int cost) { G[++Gcnt] = edge(to, head[from], cap, cost); head[from] = Gcnt; G[++Gcnt] = edge(from, head[to], 0, -cost); head[to] = Gcnt; } inline bool SPFA(int S, int T) { static int x; memset(dist, 0x3f, sizeof dist); Q.push(S); dist[S] = 0; while (!Q.empty()) { x = Q.front(); Q.pop(); vis[x] = false; for (int i = head[x]; i; i = G[i].next) { edge &e = G[i]; if (e.cap && dist[x] + e.cost < dist[e.to]) { pre[e.to] = i; dist[e.to] = dist[x] + e.cost; if (!vis[e.to]) { vis[e.to] = true; Q.push(e.to); } } } } return dist[T] != dist[0]; } inline ll Flow(int S, int T) { ll Cost = 0; int f; while (SPFA(S, T)) { f = INF; for (int i = T; i != S; i = G[pre[i] ^ 1].to) f = min(f, G[pre[i]].cap); for (int i = T; i != S; i = G[pre[i] ^ 1].to) { G[pre[i]].cap -= f; G[pre[i] ^ 1].cap += f; } Cost += f * dist[T]; } return Cost; } int main(void) { freopen("1.in", "r", stdin); Gcnt = 1; read(n); read(k); read(ms); read(me); for (int i = 1; i <= n; i++) read(s[i]); for (int i = 1; i <= n; i++) read(e[i]); for (int i = 1; i <= n; i++) { Ans += s[i]; s[i] -= e[i]; } for (int i = 1; i <= n; i++) { if (i + k <= n) AddEdge(i, i + k, 1, s[i]); else AddEdge(i, n + 2, 1, s[i]); ans[i] = Gcnt - 1; if (i < n) AddEdge(i, i + 1, k - ms - me, 0); else AddEdge(i, n + 2, k - ms - me, 0); } AddEdge(n + 1, n + 3, k - ms, 0); for (int i = 1; i <= k; i++) AddEdge(n + 3, i, INF, 0); Ans -= Flow(n + 1, n + 2); printf("%lld\n", Ans); for (int i = 1; i <= n; i++) if (G[ans[i]].cap) putchar('S'); else putchar('E'); return 0; }
相关文章推荐
- [容斥 DP] LOJ#6077. 「2017 山东一轮集训 Day7」逆序对
- LOJ #6077. 「2017 山东一轮集训 Day7」逆序对
- 【LOJ6077】「2017 山东一轮集训 Day7」逆序对 生成函数+组合数+DP
- LOJ #6077. 「2017 山东一轮集训 Day7」逆序对
- [线段树][二分图 霍尔定理]LOJ#6062 && 2017 山东一轮集训 Day2. Pair
- LOJ.6062.[2017山东一轮集训]Pair(Hall定理 线段树)
- [主席树 链剖] LOJ#6073. 「2017 山东一轮集训 Day5」距离
- [计数][容斥] LOJ#6065 || BZOJ4927 && 2017 山东一轮集训 Day3. 第一题
- [莫队维护DP] LOJ#6074. 「2017 山东一轮集训 Day6」子序列
- [倍增NTT][DP] LOJ#6059. 「2017 山东一轮集训 Day1」Sum
- loj6119 「2017 山东二轮集训 Day7」国王
- [树的同构][二分][可并堆维护哈希] LOJ#6066 || BZOJ4928 && 2017 山东一轮集训 Day3. 第二题
- [Hall定理 + 线段树] LibreOJ#6062. 「2017 山东一轮集训 Day2」Pair
- [DP][倍增NTT]LOJ#6059. 2017 山东一轮集训 Day1. Sum
- [动态网络 网络流] LOJ#6068.「2017 山东一轮集训 Day4」棋盘
- 【分块+回文自动机】LibreOJ6070(2017 山东一轮集训 Day4)[基因]题解
- [最短路 杂题] LOJ#6075. 「2017 山东一轮集训 Day6」重建
- LibreOJ 6#6062. 「2017 山东一轮集训 Day2」Pair
- [霍尔定理]「2017 山东一轮集训 Day2」LOJ 6062——PAIR
- [LOJ#6060][线性基]2017 山东一轮集训 Day1. Set