NOIP模拟(10.19)T3 放盒子

来源:互联网 发布:匿名聊天源码 编辑:程序博客网 时间:2024/05/29 16:01

放盒子

题目背景:

10.19 NOIP模拟T3

分析:费用流

这个题,我是真的没有往费用流想······

考场上还出了点问题,明明应该写双关键字排序的····然后我只排了一个关键词····明明有50分的暴力的,挂成了15分······悲剧,下次一定要注意,怎么错都轻松过样例······

这个题,考虑怎么办,显然我们对于每一个盒子要看第一,是否有盒子可以装他,第二,是否可以装下其他盒子,第三,装哪一个盒子,第四,哪一个盒子装它,每一个盒子只能用一次,有没有感觉到什么2333,我们对于每个盒子拆成两个点,为x1, x2,如果对于两个盒子,x, y, x可以装下y盒子,那么我们从x1y2连边,流量为1,费用为y盒子的面积(注意是y,就是y),然后从S向所有的第一部分点连边,流量为1,费用为0,从所有第二部分点向T连边,流量为1,费用为0,然后跑一遍最大费用最大流,用总的盒子的面积减去最大费用即可,流量限制满足每个盒子只用一次,选中了的盒子表示它可以被套住,减去费用,正确性合理。

Source

/*created by scarlyw*/#include <iostream>#include <cstring>#include <string>#include <cmath>#include <algorithm>#include <cstdio>#include <cctype>#include <vector>#include <queue>#include <map>#include <set>inline char read() {static const int IN_LEN = 1024 * 1024;static char buf[IN_LEN], *s, *t;if (s == t) {t = (s = buf) + fread(buf, 1, IN_LEN, stdin);if (s == t) return -1;}return *s++;}/*template<class T>inline void R(T &x) {static bool iosig;static char c;for (iosig = false, c = read(); !isdigit(c); c = read()) {if (c == -1) return ;if (c == '-') iosig = true;}for (x = 0; isdigit(c); c = read()) x = ((x << 2) + x << 1);if (iosig) x = -x;}//*/const int OUT_LEN = 1024 * 1024;char obuf[OUT_LEN], *oh = obuf;inline void write_char(char c) {if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf;*oh++ = c;}template<class T>inline void W(T x) {static int buf[30], cnt;if (x == 0) write_char('0');else {if (x < 0) write_char('-'), x = -x;for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;while (cnt) write_char(buf[cnt--]);}}inline void flush() {fwrite(obuf, 1, oh - obuf, stdout);}///*template<class T>inline void R(T &x) {static bool iosig;static char c;for (iosig = false, c = getchar(); !isdigit(c); c = getchar()) {if (c == -1) return ;if (c == '-') iosig = true;}for (x = 0; isdigit(c); c = getchar()) x = ((x << 2) + x << 1) + (c ^ '0');if (iosig) x = -x;}//*/const int MAXN = 400 + 10;const int INF = ~0u >> 2;int n, final = ~0u >> 1;struct data {int l, w;inline bool operator < (const data &a) const {return (l == a.l) ? (w < a.w) : (l < a.l);}} box[MAXN];struct node {int to, w, c, rev;node(int to = 0, int w = 0, int c = 0, int rev = 0) : to(to), w(w), c(c), rev(rev) {}} ;bool vis[MAXN];int ans, s ,t, cnt, sum;std::vector<node> edge[MAXN];inline void add_edge(int x, int y, int w, int c) {edge[x].push_back(node(y, w, c, edge[y].size()));edge[y].push_back(node(x, 0, -c, edge[x].size() - 1));}inline void build_graph() {R(n), cnt = 0;for (int i = 1; i <= n; ++i) R(box[i].l), R(box[i].w);std::sort(box + 1, box + n + 1);for (int i = 1; i <= n; ++i) if (box[i].l != box[i - 1].l || box[i].w != box[i - 1].w)box[++cnt] = box[i], ans += box[i].l * box[i].w;s = 0, t = 2 * cnt + 1;for (int i = 1; i <= cnt; ++i)for (int j = 1; j < i; ++j)if (box[j].w <= box[i].w)add_edge(i, j + cnt, 1, box[j].l * box[j].w);for (int i = 1; i <= cnt; ++i) add_edge(s, i, 1, 0), add_edge(i + cnt, t, 1, 0);}inline bool spfa_slf(int s, int t) {static bool vis[MAXN];static int dis[MAXN];static std::deque<int> q;for (int i = s; i <= t; ++i) vis[i] = false, dis[i] = -INF;q.push_back(t), dis[t] = 0, vis[t] = true;while (!q.empty()) {int cur = q.front();q.pop_front(), vis[cur] = false;for (int p = 0; p < edge[cur].size(); ++p) {node *e = &edge[cur][p];if (edge[e->to][e->rev].w > 0 && dis[e->to] < dis[cur] - e->c) {dis[e->to] = dis[cur] - e->c;if (!vis[e->to]) {if (!q.empty() && dis[e->to] > dis[q.front()]) q.push_front(e->to), vis[e->to] = true;else q.push_back(e->to), vis[e->to] = true;}}}}for (int i = s; i <= t; ++i)for (int p = 0; p < edge[i].size(); ++p) {node *e = &edge[i][p];e->c += dis[e->to] - dis[i];}return sum += dis[s], (dis[s] > -INF);}inline int dfs(int cur, int flow, int t) {if (cur == t) return ans -= sum * flow, flow;int ret = 0;vis[cur] = true;for (int p = 0; p < edge[cur].size(); ++p) {node *e = &edge[cur][p];if (e->w > 0 && e->c == 0 && !vis[e->to]) {int f = dfs(e->to, std::min(flow - ret, e->w), t);ret += f, e->w -= f, edge[e->to][e->rev].w += f;if (ret == flow) return flow;}}return ret;}inline void cost_flow(int s, int t) {while (spfa_slf(s, t)) {do memset(vis, false, sizeof(bool) * (t + 5));while (dfs(s, INF, t));}std::cout << ans;}int main() {//freopen("box.in", "r", stdin);//freopen("box.out", "w", stdout);build_graph();cost_flow(s, t);return 0;}