题目大意:

给出n(\(\le 200\))个盒子,第i个盒子长\(x_i\),宽\(y_i\),一个盒子可以放入长宽都大于等于它的盒子里,并且每个盒子里只能放入一个盒子(可以嵌套),嵌套的盒子的占地面积等于最外层的盒子的占地面积,求最小的占地面积之和。

题目分析:

直接打了贪心,得了50分。用脑子想想就知道第3题怎么可能这么简单,果真。
本题的本质就是能不能给一个盒子找一个长宽都大于等于它的匹配。

  • 匈牙利+贪心:如果a可以包含b,则连一条边a<-b,然后按照面积从大到小跑匈牙利,如果能够找到一个匹配,就把这个盒子的面积减掉。
  • 费用流: 将一个盒子拆成两个点1~n, n+1~2n, 如果a可以包含b,就连一条a->b+n,流量为1(只能用1个),费用为\(S_b\)的边,最后从s向1~n连流量为1,费用为0的边,从n+1~2n向t连流量为1,费用为0的边,跑最大费用最大流,将费用从总面积中减去。(费用流要去重)

code

匈牙利

#include<bits/stdc++.h>
using namespace std;namespace IO{inline int read(){int i = 0, f = 1; char ch = getchar();for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());if(ch == '-') f = -1, ch = getchar();for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');return i * f;}inline void wr(int x){if(x < 0) putchar('-'), x = -x;if(x > 9) wr(x / 10);putchar(x % 10 + '0');}
}using namespace IO;const int N = 1000;
int n;
struct node{int x, y;inline bool operator < (const node &b) const{return x*y < b.x*b.y;}
}box[N];
bool vst[N << 2];
int mateR[N << 2], ecnt, adj[N << 2], nxt[N << 2], go[N << 2], ans, to[N][N];inline bool hungry(int u){for(int i = n; i > u; i--){if(!to[u][i]) continue;if(vst[i]) continue;vst[i] = true;if(!mateR[i] || hungry(mateR[i])){mateR[i] = u;return true;}}return false;
}inline void addEdge(int u, int v){nxt[++ecnt] = adj[u], adj[u] = ecnt, go[ecnt] = v;
}int main(){n = read();for(int i = 1; i <= n; i++){int x = read(), y = read();box[i] = (node){x, y};}sort(box + 1, box + n + 1);for(int i = 1; i <= n; i++){ans += box[i].x * box[i].y;for(int j = i + 1; j <= n; j++){if(box[i].x <= box[j].x && box[i].y <= box[j].y)to[i][j] = 1;}}for(int i = n - 1; i >= 1; i--){if(hungry(i)) ans -= box[i].x * box[i].y;memset(vst, 0, sizeof vst);}wr(ans);return 0;
}

费用流

#include<bits/stdc++.h>
using namespace std;namespace IO{inline int read(){int i = 0, f = 1; char ch = getchar();for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());if(ch == '-') f = -1, ch = getchar();for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');return i * f;}inline void wr(int x){if(x < 0) putchar('-'), x = -x;if(x > 9) wr(x / 10);putchar(x % 10 + '0');}
}using namespace IO;const int N = 205, OO = 0x3f3f3f3f;
int n, ecnt = 1, adj[N << 2], nxt[100050], go[100050], cap[100050], len[100050];
int src, des, dis[N << 2], cur[N << 2], sum;
struct node{int x, y;inline bool operator < (const node &b) const{return x < b.x || (x == b.x && y < b.y);}
}box[N], unik[N];inline void addEdge(int u, int v, int c, int cost){nxt[++ecnt] = adj[u], adj[u] = ecnt, go[ecnt] = v, cap[ecnt] = c, len[ecnt] = cost;nxt[++ecnt] = adj[v], adj[v] = ecnt, go[ecnt] = u, cap[ecnt] = 0, len[ecnt] = -cost;
}int vt = 0;
inline bool SPFA(){static queue<int> que;static int vst[N << 2];memset(vst, 0, sizeof vst);while(!que.empty()) que.pop();que.push(src);for(int i = src; i <= des; i++) cur[i] = adj[i], dis[i] = -OO;dis[src] = 0;while(!que.empty()){int u = que.front(); que.pop(); vst[u] = 0;for(int e = adj[u]; e; e = nxt[e]){int v = go[e];if(dis[v] < dis[u] + len[e] && cap[e]){dis[v] = dis[u] + len[e];if(!vst[v]) vst[v] = 1, que.push(v);}}}return dis[des] !=  -OO;
}bool walk[N << 2];
inline int dinic(int u, int flow, int &ans){if(u == des){ans += flow * dis[u];return flow;}int delta, ret = 0;walk[u]=1;for(int &e = cur[u]; e; e = nxt[e]){int v = go[e];if(!walk[v] && dis[v] == dis[u] + len[e] && cap[e]){delta = dinic(v, min(cap[e], flow - ret), ans);if(delta){ret += delta, cap[e] -= delta, cap[e ^ 1] += delta;if(flow == ret) break;}}}if(flow != ret) dis[u] = -OO;return ret;
}int lenn;
inline void uni(){lenn = 0;sort(box+1,box+n+1);for(int i = 1; i <= n; i++){if(box[i].x != box[i - 1].x || box[i].y != box[i - 1].y)unik[++lenn].x = box[i].x, unik[lenn].y = box[i].y;}
}
int main(){n = read(); src = 0, des = 2 * n + 1;for(int i = 1; i <= n; i++) box[i].x = read(), box[i].y = read();uni();for(int i = 1; i <= lenn; i++){sum += unik[i].x * unik[i].y;for(int j = 1; j <= lenn; j++){if(i == j) continue;if(unik[j].x >= unik[i].x && unik[j].y >= unik[i].y) addEdge(i, j + n, 1, unik[i].x*unik[i].y);}}for(int i = 1; i <= n; i++) addEdge(src, i, 1, 0), addEdge(i + n, des, 1, 0);while(SPFA()){int ret = 0;memset(walk, 0, sizeof walk);dinic(src, OO, ret);sum -= ret;}wr(sum), putchar('\n');return 0;
}

转载于:https://www.cnblogs.com/CzYoL/p/7694086.html

NOIP 模拟 box - 费用流 / 匈牙利相关推荐

  1. CF280D-k-Maximum Subsequence Sum【模拟费用流,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/CF280D 题目大意 一个长度为nnn的序列,mmm次操作 修改一个数 询问一个区间中选出kkk段不交子段使得和最大 ...

  2. 【BZOJ3252】攻略 DFS序+线段树(模拟费用流)

    [BZOJ3252]攻略 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏. 今天他得到了一款新游戏<XX半岛> ...

  3. [Neerc2016]Mole Tunnels (模拟费用流)

    题目链接:http://codeforces.com/gym/101190 SOLUTION: 模拟费用流 这题看完之后很容易想到费用流,但是n太大了不能直接跑. 我们考虑模拟这个费用流的增广过程,每 ...

  4. BZOJ3291Alice与能源计划——匈牙利算法+模拟费用流

    题目描述 在梦境中,Alice来到了火星.不知为何,转眼间Alice被任命为火星能源部长,并立刻面临着一个严峻的考验.为 了方便,我们可以将火星抽象成平面,并建立平面直角坐标系.火星上一共有N个居民点 ...

  5. BZOJ1150[CTSC2007]数据备份Backup——模拟费用流+堆+链表

    题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游 ...

  6. BZOJ 1920 Luogu P4217 [CTSC2010]产品销售 (模拟费用流、线段树)

    题目链接 (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=1920 (luogu) https://www.luogu.org/prob ...

  7. BZOJ 5326 [JSOI2017]博弈 (模拟费用流、线段树)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=5326 题解 终于成为第8个A掉这题的人--orz tzw神仙早我6小时 本以为这东西常数 ...

  8. BZOJ 4849 [NEERC2016] Mole Tunnels (模拟费用流)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4849 题解 其实也是模拟费用流,但是这道题和一般的题目不一样,这道题是在一个完全二叉树上 ...

  9. BZOJ 4849 [NEERC2016]Mole Tunnels (模拟费用流)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4849 题解 其实也是模拟费用流,但是这道题和一般的题目不一样,这道题是在一个完全二叉树上 ...

最新文章

  1. pytorch使用horovod多gpu训练
  2. .NET Core开发实战(第22课:异常处理中间件:区分真异常与逻辑异常)--学习笔记(上)...
  3. 深度学习--Keras总结
  4. C语言中连续两个printf,在C中两个连续的printf()调用的奇怪行为
  5. 使用Scrapy框架编写爬虫
  6. action中的动态方法调用
  7. Use EventBus
  8. spring-session实现分布式集群session的共享(转)
  9. Luogu1390 公约数的和
  10. github 本地提交代码到服务器
  11. 405 Method Not Allowed 解决方案
  12. 数据结构与算法之树的孩子双亲存储结构的讲解
  13. Android TextView垂直滚动,并精准定位到最后一行
  14. 1.3 Codesys十六进制数字字符串与字节互转
  15. 欠定的三元一次方程组求解
  16. 机器学习 -- 《机器学习》(周志华) 第三章
  17. JAVA环境配置多环境(全,细,简单)
  18. 优酷自动上传软件,百度霸屏轻松到
  19. Leetcode PHP题解--D58 693. Binary Number with Alternating Bits
  20. 专业的PDF组件 Spire.PDF教程:C# 将一个 PDF 页面拆分为多页

热门文章

  1. 基于ArcSDE、Oralce空间数据库冷备份与恢复
  2. java中的神奇this
  3. 从1~N中任选出三个数,最小公倍数最大
  4. ListGetandSetDemo 集合操作get set remove add方法
  5. Brainfuck解释器(C#)
  6. VC实现微秒(十万分之一秒)休眠
  7. 台阶问题---动态规划算法
  8. 微信小程序实现支付功能
  9. 《Arduino奇妙之旅:智能车趣味制作天龙八步》一2.4 准备好了吗?
  10. There was a problem importing one of the Python modules required to run yum