[BZOJ5251][九省联考2018]劈配(网络流)
5251: [2018多省省队联测]劈配
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 33 Solved: 22
[Submit][Status][Discuss]Description
一年一度的综艺节目《中国新代码》又开始了。Zayid从小就梦想成为一名程序员,他觉得这是一个展示自己的舞台,于是他毫不犹豫地报名了。题目描述轻车熟路的Zayid顺利地通过了海选,接下来的环节是导师盲选,这一阶段的规则是这样的:总共n名参赛选手(编号从1至n)每人写出一份代码并介绍自己的梦想。接着由所有导师对这些选手进行排名。为了避免后续的麻烦,规定不存在排名并列的情况。同时,每名选手都将独立地填写一份志愿表,来对总共m位导师(编号从1至m)作出评价。志愿表上包含了共m档志愿。对于每一档志愿,选手被允许填写最多C位导师,每位导师最多被每位选手填写一次(放弃某些导师也是被允许的)。在双方的工作都完成后,进行录取工作。每位导师都有自己战队的人数上限,这意味着可能有部分选手的较高志愿、甚至是全部志愿无法得到满足。节目组对”前i名的录取结果最优“作出如下定义:前1名的录取结果最优,当且仅当第1名被其最高非空志愿录取(特别地,如果第1名没有填写志愿表,那么该选手出局)。前i名的录取结果最优,当且仅当在前i-1名的录取结果最优的情况下:第i名被其理论可能的最高志愿录取(特别地,如果第i名没有填写志愿表、或其所有志愿中的导师战队均已满员,那么该选手出局)。如果一种方案满足‘‘前n名的录取结果最优’’,那么我们可以简称这种方案是最优的。举例而言,2位导师T老师、F老师的战队人数上限分别都是1人;2位选手Zayid、DuckD分列第1、2名。那么下面3种志愿表及其对应的最优录取结果如表中所示:可以证明,对于上面的志愿表,对应的方案都是唯一的最优录取结果。每个人都有一个自己的理想值si,表示第i位同学希望自己被第si或更高的志愿录取,如果没有,那么他就会非常沮丧。现在,所有选手的志愿表和排名都已公示。巧合的是,每位选手的排名都恰好与它们的编号相同。对于每一位选手,Zayid都想知道下面两个问题的答案:在最优的录取方案中,他会被第几志愿录取。在其他选手相对排名不变的情况下,至少上升多少名才能使得他不沮丧。作为《中国新代码》的实力派代码手,Zayid当然轻松地解决了这个问题。不过他还是想请你再算一遍,来检验自己计算的正确性。Input
每个测试点包含多组测试数据第一行2个用空格隔开的非负整数T;C,分别表示数据组数、每档志愿最多允许填写的导师数目。接下来依次描述每组数据,对于每组数据:第1行两个用空格隔开的正整数n;m。n;m分别表示选手的数量、导师的数量。第2行m个用空格隔开的正整数:其中第i个整数为bi。Bi表示编号为i的导师战队人数的上限。第3行至第n+2行,每行m个用空格隔开的非负整数:其中第i+2行左起第j个数为ai,jai,j表示编号为i的选手将编号为j的导师编排在了第ai,j志愿。特别地,如果ai,j=0,则表示该选手没有将该导师填入志愿表。在这一部分,保证每行中不存在某一个正数出现超过C次(0可能出现超过C次),同时保证所有ai,j<=m。第n+3行n个用空格隔开的正整数,其中第i个整数为SiSi表示编号为i的选手的理想值。在这一部分,保证Si<=m。T<=5,m<=n<=200,Bi<=NOutput
按顺序输出每组数据的答案。对于每组数据,输出2行:第1行输出n个用空格隔开的正整数,其中第i个整数的意义为:在最优的录取方案中,编号为i的选手会被该档志愿录取。特别地,如果该选手出局,则这个数为m+1。第2行输出n个用空格隔开的非负整数,其中第i个整数的意义为:使编号为i的选手不沮丧,最少需要让他上升的排名数。特别地,如果该选手一定会沮丧,则这个数为i。Sample Input
3 5
2 2
1 1
2 2
1 2
1 1
2 2
1 1
1 2
1 2
2 1
2 2
1 1
0 1
0 1
2 2Sample Output
2 1
1 0
1 2
0 1
1 3
0 1
三组数据分别与【题目描述】中的三个表格对应。
对于第1 组数据:由于选手1 没有填写第一志愿,所以他一定无法被第一志愿录取,也就一定会沮丧。
选手2 按原排名就不沮丧,因此他不需要提升排名。
对于第2 组和第3 组数据:1 号选手都不需要提升排名。
而希望被第一志愿录取 的2 号选手都必须升到第1 名才能如愿。HINT
Source
D2唯一有区分度的题。。正解好像有4种,下面说一个Dinic做法。
首先如果你非常巧妙地避开了所有有关二分图和网络流的思路,你也可以通过各种数据分治拿到70分,但是码量感觉不可想象。
先之考虑第一问,第二问实在不行二分答案或者暴力枚举跑m次第一问就好。
看原题面可以看到b[i]=1的50分,这启发我们想到二分图,因为每个选手对应一位导师,而匈牙利算法正好保证了每次增广都保证前面的选手都能匹配上。那么b[i]>1的怎么处理呢?不就是网络流嘛,直接将导师的点向汇点连容量为b[i]的边就好了。
考虑具体做法,对于当前考虑的选手,每次向一组导师全部连边,如果增广成功则考虑下一个选手。
怎么证明是对的呢?首先我们知道网络流每次能够增广当且仅当流量能变大,所以在增广这个点的同时不可能让前面所有的选手找不到匹配,所以我们一边加边一边跑Dinic即可。
至于第二问,第一反应肯定是二分答案然后暴力重建图,这样好像是可以过的,但是我们可以先连上所有这个点的边,然后从第一名开始增广,知道找不到增广则停止,这样复杂度就和上面第一问同阶了。$O(f(n,n^2)n)$,其中$f(n,m)$表示n个点m条边的二分图匹配的复杂度,也就是$O(nm)$,实际上跑不满。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define rep(i,l,r) for (int i=l; i<=r; i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
using namespace std; const int N=,M=,inf=;
int n,m,k,cas,ans,cnt,S,T,b[N],dis[N],h[N],q[M],nxt[M],to[M],f[M],res[N];
vector<int>V[N][N]; void add(int u,int v,int w){
to[++cnt]=v; f[cnt]=w; nxt[cnt]=h[u]; h[u]=cnt;
to[++cnt]=u; f[cnt]=; nxt[cnt]=h[v]; h[v]=cnt;
} void init(){
cnt=; S=n+m+; T=n+m+;
memset(h,,sizeof(h));
rep(i,,n) add(S,i,);
rep(i,,m) add(i+n,T,b[i]);
} bool bfs(){
rep(i,,T) dis[i]=;
dis[S]=; q[]=S;
for (int st=,ed=; st!=ed; ){
int x=q[++st];
For(i,x) if (!dis[k=to[i]] && f[i])
dis[k]=dis[x]+,q[++ed]=k;
}
return dis[T];
} int dfs(int x,int lim){
if (x==T) return lim;
int c=;
For(i,x) if (dis[k=to[i]]==dis[x]+ && f[i]){
int t=dfs(k,min(lim-c,f[i]));
f[i]-=t; f[i^]+=t; c+=t;
if (c==lim) return lim;
}
if (!c) dis[x]=-;
return c;
} bool work(int x,int l,int r){
rep(i,l,r) rep(j,,(int)V[x][i].size()-) add(x,V[x][i][j]+n,);
if (bfs()) { dfs(S,inf); return ; }
return ;
} int main(){
for (scanf("%d%*d",&cas); cas--; ){
scanf("%d%d",&n,&m);
rep(i,,m) scanf("%d",&b[i]);
rep(i,,n) rep(j,,m) V[i][j].clear();
rep(i,,n) rep(j,,m) scanf("%d",&k),V[i][k].push_back(j);
init();
rep(i,,n){
for (res[i]=; res[i]<=m; res[i]++) if (work(i,res[i],res[i])) break;
printf("%d ",res[i]);
}
puts("");
rep(i,,n){
scanf("%d",&k); ans=i; init();
if (!work(i,,k)) { printf("%d ",i); continue; }
for (int j=; --ans; j++){
if (res[j]>m) continue;
if (!work(j,res[j],res[j])) break;
}
printf("%d ",ans);
}
puts("");
}
return ;
}
[BZOJ5251][九省联考2018]劈配(网络流)的更多相关文章
- BZOJ5251 八省联考2018劈配(网络流)
劈配,匹配,网络流.那么考虑怎么跑网络流. 先看第一问.首先套路的建出超源超汇.不用想也知道导师向汇连容量为战队人数上限的边.特别地,给出局也建一个点,向汇连容量inf的边(似乎没有必要).对于一个新 ...
- BZOJ5251:[九省联考2018]劈配——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5251 https://loj.ac/problem/2477 <-可以看数据 https: ...
- luogu P4382 [九省联考2018]劈配
luogu 我记得我第一次做这道题的时候屁都不会qwq 先考虑第一问,暴力是依次枚举每个人,然后从高到低枚举志愿,枚举导师,能选就选.但是可以发现前面的人选的导师可能会导致后面的人本来可以选到这个志愿 ...
- [八省联考2018] 劈配 mentor
Description 一年一度的综艺节目<中国新代码>又开始了.Zayid 从小就梦想成为一名程序员,他觉得这是一个展示自己的舞台,于是他毫不犹豫地报名了. Input 轻车熟路的Zay ...
- BZOJ.5251.[八省联考2018]劈配mentor(最大流)
BZOJ 洛谷 对于每个人,每次枚举一个志愿看是否能增广即可. 对于第二问,可以保留第一问中\(n\)次增广前后的\(n\)张图,二分,在对应图上看是否能增广即可. 貌似匈牙利的某种写法比网络流优多了 ...
- 洛谷P4382 [八省联考2018]劈配(网络流,二分答案)
洛谷题目传送门 说不定比官方sol里的某理论最优算法还优秀一点? 所以\(n,m\)说不定可以出到\(1000\)? 无所谓啦,反正是个得分题.Orz良心出题人,暴力有70分2333 思路分析 正解的 ...
- P4382 [八省联考2018]劈配
题目链接 题意分析 受到了\(olinr\ \ julao\)的影响 写了匈牙利算法 首先 我们对于每一个人 从高到低枚举志愿 如果当前志愿的老师有剩余的话 那么我们就选 否则的话 我们看看谁的那个志 ...
- [九省联考2018]秘密袭击coat
[九省联考2018]秘密袭击coat 研究半天题解啊... 全网几乎唯一的官方做法的题解:链接 别的都是暴力.... 要是n=3333暴力就完了. 一.问题转化 每个联通块第k大的数,直观统计的话,会 ...
- 【BZOJ5250】[九省联考2018]秘密袭击(动态规划)
[BZOJ5250][九省联考2018]秘密袭击(动态规划) 题面 BZOJ 洛谷 给定一棵树,求其所有联通块的权值第\(k\)大的和. 题解 整个\(O(nk(n-k))\)的暴力剪剪枝就给过了.. ...
随机推荐
- 【BZOJ】1703: [Usaco2007 Mar]Ranking the Cows 奶牛排名
[题意]给定n头牛和m对大小关系,求最坏情况下至少还需要比较几对奶牛的大小(在未确定顺序的奶牛对中随机比较) [算法]floyd求传递闭包 [题解]可达说明大小已知,则不可达点对数量就是最少比较次数. ...
- Bazinga(HDU5510+KMP)
t题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5510 题目: 题意:找到一个编号最大的字符串满足:存在一个编号比它小的字符串不是它的字串. 思路:K ...
- Coursera在线学习---第十节.大规模机器学习(Large Scale Machine Learning)
一.如何学习大规模数据集? 在训练样本集很大的情况下,我们可以先取一小部分样本学习模型,比如m=1000,然后画出对应的学习曲线.如果根据学习曲线发现模型属于高偏差,则应在现有样本上继续调整模型,具体 ...
- DTW 算法(转)
DTW为(Dynamic Time Warping,动态时间归准)的简称.应用很广,主要是在模板匹配中,比如说用在孤立词语音识别,计算机视觉中的行为识别,信息检索等中.可能大家学过这些类似的课程都看到 ...
- 使用IDA PRO+OllyDbg+PEview 追踪windows API 动态链接库函数的调用过程
使用IDA PRO+OllyDbg+PEview 追踪windows API 动态链接库函数的调用过程 http://blog.csdn.net/liujiayu2/article/details/5 ...
- Meld:文件及目录对比工具
Meld:文件及目录对比工具 http://wowubuntu.com/meld.html http://meld.sourceforge.net/
- 斯坦福开源无Bug的随机计算图Certigrad
斯坦福开源无Bug的随机计算图Certigrad https://news.cnblogs.com/n/573690/ ttps://github.com/dselsam/certigrad
- 【bzoj4448】SCOI2015 情报传递
树剖,可以相当于一个染色问题,以及询问先前节点的染色个数. 把第二种操作离线掉,然后用线段树模拟即可. #include<bits/stdc++.h> #define N 800010 # ...
- echo常用操作
echo -n 不换行输出 [root@C ~]# echo -n "peter" ; echo "linux" peterlinux echo -e 输出转义 ...
- 大小端 Big-Endian 与 Little-Endian
应该说没做底层开发(硬件或驱动)的人很可能不会彻底理解大小端的概念,大小端不是简单的一句“大端在前”还是“小端在前”能够概括的问题.在cpu, 内存, 操作系统, 编译选项, 文件,网络传输中均有大小 ...
