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当然轻松地解决了这个问题。

不过他还是想请你再算一遍,来检验自己计算的正确性。

Solution

直接暴力网络流判断一个人能否选到这个志愿,不能选到我们就把新加的边去掉就可以了

然后对于第二问,显然可以二分答案

但是每一次暴力建图是不行的,实际上我们可以把图存下来,这样每一次 \(check\) 就是找一条增广路的时间了,所以复杂度瓶颈反而在第一问了

复杂度 \(O(n*m*flow)\)

#include<bits/stdc++.h>
using namespace std;
const int N=510,M=N*N,inf=1e8;
int n,m,b[N],a[N][N],C,head[N],nxt[M],num=1,to[M],dis[M],S=0,T;
inline void link(int x,int y,int z){
nxt[++num]=head[x];to[num]=y;head[x]=num;dis[num]=z;
nxt[++num]=head[y];to[num]=x;head[y]=num;dis[num]=0;
}
int f[N],dep[N],s[N];
vector<int>v[N][N];queue<int>Q;
inline bool bfs(){
for(int i=S;i<=T;i++)dep[i]=0;
Q.push(S);dep[S]=1;
while(!Q.empty()){
int x=Q.front();Q.pop();
for(int i=head[x];i;i=nxt[i]){
int u=to[i];
if(dis[i]<=0 || dep[u])continue;
dep[u]=dep[x]+1;Q.push(u);
}
}
return dep[T];
}
inline int dfs(int x,int flow){
if(x==T || !flow)return flow;
int tot=0,u,t;
for(int i=head[x];i;i=nxt[i]){
u=to[i];
if(dis[i]<=0 || dep[u]!=dep[x]+1)continue;
t=dfs(u,min(flow,dis[i]));
dis[i]-=t;dis[i^1]+=t;
flow-=t;tot+=t;
if(!flow)break;
}
if(!tot)dep[x]=-1;
return tot;
}
inline int Dinic(){
int ret=0,t=0;
while(bfs()){
t=dfs(S,inf);
while(t)ret+=t,t=dfs(S,inf);
}
return ret;
}
int st[N],reb[N],top=0;
inline bool ok(int x,int y){
if(v[x][y].empty())return false;
int last=num;top=0;
st[++top]=x;reb[top]=head[x];
for(int i=v[x][y].size()-1;i>=0;i--){
int k=v[x][y][i];
st[++top]=n+k;reb[top]=head[n+k];
link(x,n+k,1);
}
if(Dinic())return true;
num=last;
while(top)head[st[top]]=reb[top],top--;
return false;
}
inline void cmp(){for(int i=S;i<=T;i++)head[i]=0;num=1;}
inline void Clear(){
cmp();
for(int i=1;i<=n;i++){
f[i]=0;
for(int j=1;j<=m;j++)vector<int>().swap(v[i][j]);
}
}
struct data{
int head[N],to[5010],nxt[5010],dis[5010],num;
}e[N];
inline bool check(int x,int y){
num=e[y-1].num;
for(int i=S;i<=T;i++)head[i]=e[y-1].head[i];
for(int i=2;i<=num;i++)
nxt[i]=e[y-1].nxt[i],to[i]=e[y-1].to[i],dis[i]=e[y-1].dis[i];
link(S,x,1);int t=N;
for(int j=1;j<=m;j++)if(ok(x,j)){t=j;break;}
return t<=s[x];
}
inline void work(){
memset(e,0,sizeof(e));
scanf("%d%d",&n,&m);T=n+m+1;
for(int i=1;i<=m;i++)scanf("%d",&b[i]),link(i+n,T,b[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
if(a[i][j])v[i][a[i][j]].push_back(j);
}
e[0].num=num;
for(int k=2;k<=num;k++)
e[0].nxt[k]=nxt[k],e[0].to[k]=to[k],e[0].dis[k]=dis[k];
for(int k=S;k<=T;k++)e[0].head[k]=head[k];
for(int i=1;i<=n;i++)scanf("%d",&s[i]);
for(int i=1;i<=n;i++){
link(S,i,1);
for(int j=1;j<=m;j++)
if(ok(i,j)){f[i]=j;break;}
e[i].num=num;
for(int k=2;k<=num;k++)
e[i].nxt[k]=nxt[k],e[i].to[k]=to[k],e[i].dis[k]=dis[k];
for(int k=S;k<=T;k++)e[i].head[k]=head[k];
}
for(int i=1;i<=n;i++)if(!f[i])f[i]=m+1;
for(int i=1;i<=n;i++)printf("%d ",f[i]);puts("");
for(int i=1;i<=n;i++){
if(f[i]<=s[i]){printf("0 ");continue;}
int ret=i,l=1,r=i-1,mid;
while(l<=r){
mid=(l+r)>>1;
if(check(i,mid))ret=i-mid,l=mid+1;
else r=mid-1;
}
printf("%d ",ret);
}
Clear();puts("");
}
int main(){
freopen("mentor.in","r",stdin);
freopen("mentor.out","w",stdout);
int Ti;cin>>Ti>>C;
while(Ti--)work();
return 0;
}

bzoj 5251: [2018多省省队联测]劈配的更多相关文章

  1. bzoj千题计划321:bzoj5251: [2018多省省队联测]劈配(网络流 + 二分)

    https://www.lydsy.com/JudgeOnline/problem.php?id=5251 第一问: 左边一列点代表学生,右边一列点代表导师 导师向汇点连流量为 人数限制的 边 然后从 ...

  2. bzoj5251 [2018多省省队联测]劈配

    直接网络流模拟即可AC. 可持久化+暴力=90分, 可持久化+二分=30分, 暴力加边+二分=100分. 我也很无奈啊. Ivan便涨红了脸,额上的青筋条条绽出,争辩道,“memcpy也是可持久化…… ...

  3. bzoj 5249 [2018多省省队联测] IIIDX

    bzoj 5249 [2018多省省队联测] IIIDX Link Solution 首先想到贪心,直接按照从大到小的顺序在后序遍历上一个个填 但是这样会有大问题,就是有相同的数的时候,会使答案不优 ...

  4. bzoj 5248: [2018多省省队联测]一双木棋

    Description 菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手.棋局开始时,棋盘上没有任何棋子, 两人轮流在格子上落子,直到填满棋盘时结束.落子的规则是:一个格子可以落子 ...

  5. BZOJ 5249: [2018多省省队联测]IIIDX(贪心 + 线段树)

    题意 这一天,\(\mathrm{Konano}\) 接到了一个任务,他需要给正在制作中的游戏 \(\mathrm{<IIIDX>}\) 安排曲目 的解锁顺序.游戏内共有\(n\) 首曲目 ...

  6. BZOJ 5248: [2018多省省队联测]一双木棋(对抗搜索)

    Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 439  Solved: 379[Submit][Status][Discuss] Descriptio ...

  7. 【刷题】BZOJ 5249 [2018多省省队联测]IIIDX

    Description [题目背景] Osu听过没?那是Konano最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在,他在世界知名游戏公司KONMAI内工作,离他的梦想也 ...

  8. 【刷题】BZOJ 5248 [2018多省省队联测]一双木棋

    Description 菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手.棋局开始时,棋盘上没有任何棋子, 两人轮流在格子上落子,直到填满棋盘时结束.落子的规则是:一个格子可以落子 ...

  9. bzoj 5252: [2018多省省队联测]林克卡特树

    Description 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战. 游戏中有一个叫做& ...

随机推荐

  1. 【alpha冲刺】随笔合集

    Daily Scrum Meeting 第一天 [Alpha]Daily Scrum Meeting第一次 第二天 [Alpha]Daily Scrum Meeting第二次 第三天 [Alpha]D ...

  2. 进程与fork()、wait()、exec函数组

    进程与fork().wait().exec函数组 内容简介:本文将引入进程的基本概念:着重学习exec函数组.fork().wait()的用法:最后,我们将基于以上知识编写Linux shell作为练 ...

  3. Beta项目复审

    Beta项目复审 复审人:张宇光 所属团队:MyGod 团队成员:程环宇.王田路.张芷祎.张宇光.王婷婷 团队排名: SW_HW4-team团队 hyw-team团队 Java-Team团队 C++团 ...

  4. 在Windows上安装「算法 第四版」组件

    这篇文档将向你介绍如何在Windows系统上安装本书将用到的Java开发环境,同时我们也提供了一个手把手的.使用我们提供的DrJava工具或者用命令行来创建.编译和运行你的第一个Java程序的手册,这 ...

  5. 浅谈数据结构vector

    vector: 又名 向量 1.C++中的一种数据结构. 2.是一个类. 3.相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间的目的. A.使用时, ...

  6. 【iOS】swift 枚举

    枚举语法 你可以用enum开始并且用大括号包含整个定义体来定义一个枚举: enum SomeEnumeration { // 在这里定义枚举 } 这里有一个例子,定义了一个包含四个方向的罗盘: enu ...

  7. 51Nod P1100 斜率最大

    传送门: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1100 由于2 <= N <= 10000, 所以 ...

  8. C# Unity游戏开发——Excel中的数据是如何到游戏中的 (四)2018.4.3更新

    本帖是延续的:C# Unity游戏开发--Excel中的数据是如何到游戏中的 (三) 最近项目不算太忙,终于有时间更新博客了.关于数据处理这个主题前面的(一)(二)(三)基本上算是一个完整的静态数据处 ...

  9. JAVA_SE基础——70.Math类

    package cn.itcast.other; /*  Math 数学类, 主要是提供了很多的数学公式.    abs(double a)  获取绝对值  ceil(double a)  向上取整 ...

  10. 看到一个对CAP简单的解释

    一个分布式系统里面,节点组成的网络本来应该是连通的.然而可能因为一些故障,使得有些节点之间不连通了,整个网络就分成了几块区域.数据就散布在了这些不连通的区域中.这就叫分区.当你一个数据项只在一个节点中 ...