不知道这个Zayid是谁...

题意:

有n个人,m个导师。每个导师能接纳bi个人,每个人对于这m个导师都有一个志愿档次。

优先满足靠前的人,问到最后每个人匹配的导师是他的第几志愿。

每个人又有一个限制si,问至少前进多少名才能被志愿档次不大于si的导师录取。

解:

首先发现,每个志愿档次只能填一个人的时候,可以直接贪心。否则在同一志愿档次内选择不同的导师会对后面有影响。

这时我们就可以利用网络流。

一个流量代表一个的归属,动态加边。

对于每个人枚举志愿档次,添加流向导师的边。然后看是否有流量。

如果有流量那么他就归于该志愿档次。

第二问,答案可以二分。

很简朴的想法是对于每个二分出来的值,重新建图来一遍。这样复杂度就是Tnlogn * nm,显然不行。

发现每次重新建图的时候我们进行了很多一模一样的操作。于是考虑把前k个人的网络流状态保存下来,之后直接调用。

但是太麻烦了...我们又发现一种很巧妙的方法:判断在前k个人加完之后是否可行,其实是看哪些导师还可以接纳人。于是我们从汇点出发,反向DFS,能够得到每次从哪些导师出发有增广路,就是哪些导师还能接纳。

然后二分的时候直接O(m)判定。

这样我们发现有90分,超时一个点。

回想第一问网络流的时候,如果一个志愿档次没有流量,那么这些加的边就没有用,不妨删了。

然后就A了...

 #include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm> const int N = , INF = 0x3f3f3f3f; int b[N], C, n, m, a[N][N], s[N], mat[N];
std::vector<int> topo[N][N]; namespace fl { struct Edge {
int nex, v, c;
}edge[]; int top = ; int d[N << ], e[N << ], E[N << ], TOP;
bool vis[N][N << ];
std::queue<int> Q; inline void add(int x, int y, int z) {
top++;
edge[top].v = y;
edge[top].c = z;
edge[top].nex = e[x];
e[x] = top; top++;
edge[top].v = x;
edge[top].c = ;
edge[top].nex = e[y];
e[y] = top;
return;
} inline bool BFS(int s, int t) {
memset(d, , sizeof(d));
d[s] = ;
Q.push(s);
while(!Q.empty()) {
int x = Q.front();
Q.pop();
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(!edge[i].c || d[y]) {
continue;
}
d[y] = d[x] + ;
Q.push(y);
}
}
return d[t];
} int DFS(int x, int t, int maxF) {
if(x == t) {
return maxF;
}
int Ans = ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(!edge[i].c || d[x] + != d[y]) {
continue;
}
int temp = DFS(y, t, std::min(edge[i].c, maxF - Ans));
if(!temp) {
d[y] = INF;
}
Ans += temp;
edge[i].c -= temp;
edge[i ^ ].c += temp;
if(Ans == maxF) {
break;
}
}
return Ans;
} inline int dinic(int s, int t) {
int Ans = ;
while(BFS(s, t)) {
Ans += DFS(s, t, INF);
}
return Ans;
} void DFS(int x, int k) {
vis[k][x] = ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(!edge[i ^ ].c || vis[k][y]) {
continue;
}
DFS(y, k);
}
return;
} inline bool check(int x, int mid) {
for(int k = ; k <= s[x]; k++) {
for(int jj = topo[x][k].size() - ; jj >= ; jj--) {
int j = topo[x][k][jj];
if(vis[x - mid - ][j + n]) {
return ;
}
}
}
return ;
} inline void solve() {
memset(vis[], -, sizeof(vis[]));
int S = n + m + , T = n + m + ;
for(int i = ; i <= m; i++) {
add(n + i, T, b[i]);
}
for(int i = ; i <= n; i++) {
add(S, i, );
mat[i] = ;
for(int k = ; k <= m; k++) {
TOP = top;
E[i] = e[i];
for(int jj = topo[i][k].size() - ; jj >= ; jj--) {
int j = topo[i][k][jj];
E[n + j] = e[n + j];
add(i, n + j, );
}
int temp = dinic(S, T);
if(temp) {
mat[i] = k;
break;
}
else {
e[i] = E[i];
for(int jj = topo[i][k].size() - ; jj >= ; jj--) {
int j = topo[i][k][jj];
e[n + j] = E[n + j];
}
top = TOP;
}
}
if(!mat[i]) {
mat[i] = m + ;
}
DFS(T, i);
}
for(int i = ; i <= n; i++) {
printf("%d ", mat[i]);
}
puts("");
// first OVER for(int i = ; i <= n; i++) {
if(mat[i] <= s[i]) {
printf("0 ");
continue;
}
int l = , r = i;
while(l < r) {
int mid = (l + r) >> ;
if(check(i, mid)) {
r = mid;
}
else {
l = mid + ;
}
}
printf("%d ", r);
}
puts("");
return;
} inline void clear() {
memset(e, , sizeof(e));
top = ;
memset(vis, , sizeof(vis));
return;
}
} inline void solve() {
scanf("%d%d", &n, &m);
for(int i = ; i <= m; i++) {
scanf("%d", &b[i]);
}
for(int i = ; i <= n; i++) {
for(int j = ; j <= m; j++) {
scanf("%d", &a[i][j]);
if(a[i][j]) {
topo[i][a[i][j]].push_back(j);
}
}
}
for(int i = ; i <= n; i++) {
scanf("%d", &s[i]);
}
// read over fl::solve();
return;
} inline void clear() {
for(int i = ; i <= n; i++) {
for(int j = ; j <= m; j++) {
topo[i][j].clear();
}
}
fl::clear();
return;
} int main() { int T;
scanf("%d%d", &T, &C);
while(T--) {
solve();
if(T) {
clear();
}
}
return ;
}

AC代码

我发现D2T1都好毒瘤...屠龙勇士也是的。

洛谷P4382 劈配的更多相关文章

  1. 洛谷P4382 [八省联考2018]劈配(网络流,二分答案)

    洛谷题目传送门 说不定比官方sol里的某理论最优算法还优秀一点? 所以\(n,m\)说不定可以出到\(1000\)? 无所谓啦,反正是个得分题.Orz良心出题人,暴力有70分2333 思路分析 正解的 ...

  2. 洛谷P5289 皮配

    解:观察一波部分分. 首先小数据直接暴力4n,然后考虑背包.设f[i][a][b][c]表示前i个学校中前三位导师分别有多少人,第四位导师可以直接推出来. 然后暴力枚举每一个人放在哪进行背包. 进一步 ...

  3. 【BZOJ5251】【八省联考2018】劈配(网络流,二分答案)

    [BZOJ5251][八省联考2018]劈配(网络流,二分答案) 题面 洛谷 BZOJ Description 一年一度的综艺节目<中国新代码>又开始了. Zayid从小就梦想成为一名程序 ...

  4. [洛谷P3643] [APIO2016]划艇

    洛谷题目链接:[APIO2016]划艇 题目描述 在首尔城中,汉江横贯东西.在汉江的北岸,从西向东星星点点地分布着 \(N\) 个划艇学校,编号依次为 \(1\) 到 \(N\).每个学校都拥有若干艘 ...

  5. 洛谷P1991 无线通讯网

    P1991 无线通讯网 170通过 539提交 题目提供者洛谷OnlineJudge 标签图论 难度普及+/提高 提交该题 讨论 题解 记录 最新讨论 怎么又炸了 为啥一直40!求解! UKE:inv ...

  6. BZOJ5251:[九省联考2018]劈配——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5251 https://loj.ac/problem/2477  <-可以看数据 https: ...

  7. COCI2017-2018#3 Dojave || 洛谷P4443

    题目传送门............................................................................................... ...

  8. 【洛谷4933】大师(DP)

    题目: 洛谷4933 分析: (自己瞎yy的DP方程竟然1A了,写篇博客庆祝一下) (以及特斯拉电塔是向Red Alert致敬吗233) 这里只讨论公差不小于\(0\)的情况,小于\(0\)的情况进行 ...

  9. 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)

    洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...

随机推荐

  1. smash:一个类unix内核

    前言 每一个蹩脚的C++程序员都有一颗做操作系统内核的心.我从大学毕业开始就对操作系统内核感兴趣,将其看作是术之尽头,可惜那时候一直在无忧无虑的忙着玩网游,也就搁置了.随着时间的推移,逐渐就将其淡忘了 ...

  2. JavaWeb-Servlet-Tomcat

    Servlet就是运行在服务器上的Java类.Servlet容器为javaweb应用提供运行时环境,负责管理Servlet和JSP的生命周期,以及管理它们的共享数据. Servlet容器软件——Tom ...

  3. tac命令详解

    基础命令学习目录首页 原文链接:http://blog.chinaunix.net/uid-128922-id-289974.html 有许多命令都可以查看文件,不同的命令有不同的优点,可以针对不同的 ...

  4. (转)Django 数据库

         转:https://blog.csdn.net/ayhan_huang/article/details/77575186      目录 数据库说明 配置数据库 在屏幕输出orm操作对应的s ...

  5. java程序设计课程实验报告3

    北京电子科技学院(BESTI) 实     验    报     告 课程:java程序设计    班级:1353  姓名:陈都  学号:20135328 成绩:             指导教师:娄 ...

  6. 20162328蔡文琛 week11 大二

    20162328 2017-2018-1 <程序设计与数据结构>第十一周学习总结 教材学习内容总结 在无向图中,表示边的顶点对是无序的. 如果图中的两个顶点之间有边链接,则称它们是领接的. ...

  7. 《[C#] int与System.Int32有什么区别》

    最近园里的TeamOne写了一篇<[C#] int与System.Int32有什么区别>,发现里面有不少精彩的评论,所以忍不住想这篇文章总结一下:> 本文的主要参考资料: 1.< ...

  8. week2-作业2

    项目地址:https://git.coding.net/Rainoob/calculate.git ·1.需求分析:程序可以根据输入的参数n随机产生n道四则运算计算题,每个数字在0-100之间.运算符 ...

  9. Oracle中创建自增字段方法

    oracle没有ORACLE自增字段这样的功能,但是通过触发器(trigger)和序列(sequence)可以实现. 下面给大家讲个例子: 1.在Oracle中创建一个表: .创建一个表 ) prim ...

  10. [BUAA_SE_2017]个人阅读作业 + 总结

    个人阅读作业 银弹 银弹是指能让狼人一枪毙命的致命子弹,对于软件工程而言,我觉得是不存在银弹的.每一项软件开发都是极为特殊的,有特定的需求.特定的功能,如果存在银弹能够直击要害解决问题,那么软件的开发 ...