https://www.lydsy.com/JudgeOnline/problem.php?id=5251

第一问:

左边一列点代表学生,右边一列点代表导师

导师向汇点连流量为 人数限制的 边

然后从第一个学生的第一志愿往里面加边

如果当前学生的当前志愿可以满足,即目前网络流可以满流,保留这一志愿的边,然后下一个学生

否则,删除这一志愿的边,然后下一个志愿

第二问:

二分这个学生要前进多少名

假设是学生i要前进x名

把前i-x-1名的学生 在第一问中满足的志愿 的边加进去

在把学生i的边加进去

判断是否满流

注意判断满流的时候 不包括前i-x-1名学生里没有任何导师的学生

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm> using namespace std; #define N 201
#define M 80801 int n,m; int lim[N];
int a[N][N][N];
int cnt[N][N]; int dream[N]; int tot=;
int src,decc;
int lev[N<<],cur[N<<];
int front[M<<],nxt[M<<],to[M<<],cap[M<<];
queue<int>q; int st[N]; inline void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} inline void init()
{
read(n); read(m);
decc=n+m+;
for(int i=;i<=m;++i) read(lim[i]);
int x;
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
{
read(x);
if(x) a[i][x][++cnt[i][x]]=j;
}
for(int i=;i<=n;++i) read(dream[i]);
} inline void add(int u,int v,int w)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; cap[tot]=w;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; cap[tot]=;
} inline bool bfs()
{
for(int i=;i<=decc;++i) cur[i]=front[i],lev[i]=-;
while(!q.empty()) q.pop();
q.push(src);
lev[src]=;
int now,t;
while(!q.empty())
{
now=q.front();
q.pop();
for(int i=front[now];i;i=nxt[i])
{
t=to[i];
if(lev[t]==- && cap[i])
{
lev[t]=lev[now]+;
if(t==decc) return true;
q.push(t);
}
}
}
return false;
} inline int dinic(int now,int flow)
{
if(now==decc) return flow;
int rest=,delta;
for(int &i=cur[now];i;i=nxt[i])
if(cap[i] && lev[to[i]]==lev[now]+)
{
delta=dinic(to[i],min(flow-rest,cap[i]));
if(delta)
{
rest+=delta;
cap[i]-=delta; cap[i^]+=delta;
if(rest==flow) break;
}
}
if(rest!=flow) lev[now]=-;
return rest;
} void solve1()
{
for(int i=;i<=m;++i) add(n+i,decc,lim[i]);
int ok;
for(int i=;i<=n;++i)
{
add(src,i,);
for(int j=;j<=m;++j)
if(cnt[i][j])
{
for(int k=;k<=cnt[i][j];++k) add(i,n+a[i][j][k],);
if(bfs())
{
dinic(src,i);
st[i]=j;
break;
}
else
{
for(int k=,h=tot;k<=cnt[i][j];++k,h-=) cap[h]=cap[h-]=;
}
}
}
for(int i=;i<=n;++i) printf("%d ",st[i] ? st[i] : m+);
putchar('\n');
} inline bool check(int x,int goal)
{
tot=;
memset(front,,sizeof(front));
for(int i=;i<=m;++i) add(n+i,decc,lim[i]);
int ok=;
for(int i=;i<goal;++i)
{
add(src,i,);
if(!st[i])
{
ok++;
continue;
}
for(int j=;j<=cnt[i][st[i]];++j) add(i,n+a[i][st[i]][j],);
}
add(src,x,);
for(int i=;i<=dream[x];++i)
for(int j=;j<=cnt[x][i];++j) add(x,n+a[x][i][j],);
while(bfs()) ok+=dinic(src,goal);
return ok==goal;
} void solve2()
{
int l,r,mid,ans;
for(int i=;i<=n;++i)
{
if(st[i] && st[i]<=dream[i])
{
printf("0 ");
continue;
}
ans=i;
l=; r=i-;
while(l<=r)
{
mid=l+r>>;
if(check(i,i-mid)) ans=mid,r=mid-;
else l=mid+;
}
printf("%d ",ans);
}
putchar('\n');
} void clear()
{
memset(st,,sizeof(st));
memset(cnt,,sizeof(cnt));
memset(front,,sizeof(front));
tot=;
} int main()
{
//freopen("mentor.in","r",stdin);
//freopen("mentor.out","w",stdout);
int T,C;
read(T); read(C);
while(T--)
{
clear();
init();
solve1();
solve2();
}
}

bzoj千题计划321:bzoj5251: [2018多省省队联测]劈配(网络流 + 二分)的更多相关文章

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

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

  2. bzoj 5251: [2018多省省队联测]劈配

    Description 一年一度的综艺节目<中国新代码>又开始了. Zayid从小就梦想成为一名程序员,他觉得这是一个展示自己的舞台,于是他毫不犹豫地报名了. 题目描述 轻车熟路的Zayi ...

  3. bzoj千题计划300:bzoj4823: [Cqoi2017]老C的方块

    http://www.lydsy.com/JudgeOnline/problem.php?id=4823 讨厌的形状就是四联通图 且左右各连一个方块 那么破坏所有满足条件的四联通就好了 按上图方式染色 ...

  4. bzoj千题计划324:bzoj5249: [2018多省省队联测]IIIDX(线段树)

    https://www.lydsy.com/JudgeOnline/problem.php?id=5249 把树建出来 如果所有的d互不相同,后续遍历即可 现在有的d相同 将d从小到大排序,考虑如何将 ...

  5. bzoj千题计划307:bzoj5248: [2018多省省队联测]一双木棋

    https://www.lydsy.com/JudgeOnline/problem.php?id=5248 先手希望先手得分减后手得分最大,后手希望先手得分减后手得分最小 棋盘的局面一定是阶梯状,且从 ...

  6. bzoj千题计划196:bzoj4826: [Hnoi2017]影魔

    http://www.lydsy.com/JudgeOnline/problem.php?id=4826 吐槽一下bzoj这道题的排版是真丑... 我还是粘洛谷的题面吧... 提供p1的攻击力:i,j ...

  7. bzoj千题计划177:bzoj1858: [Scoi2010]序列操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=1858 2018 自己写的第1题,一遍过 ^_^ 元旦快乐 #include<cstdio> ...

  8. bzoj千题计划280:bzoj4592: [Shoi2015]脑洞治疗仪

    http://www.lydsy.com/JudgeOnline/problem.php?id=4592 注意操作1 先挖再补,就是补的范围可以包含挖的范围 SHOI2015 的题 略水啊(逃) #i ...

  9. bzoj千题计划317:bzoj4650: [Noi2016]优秀的拆分(后缀数组+差分)

    https://www.lydsy.com/JudgeOnline/problem.php?id=4650 如果能够预处理出 suf[i] 以i结尾的形式为AA的子串个数 pre[i] 以i开头的形式 ...

随机推荐

  1. 自学Python3.6-算法 二分查找算法

    自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...

  2. nginx.conf(centos6, 1.12)主配置文件修改

    #nginx1.12 centos6.xuser admin admin;worker_processes 4; error_log /data/services/logs/nginx_error.l ...

  3. bzoj2288 生日礼物 (线段树)

    我当然想选最大的子段和啦 但要选M次 那不一定就是最好的 所以提供一个反悔的选项,我选了一段以后,就把它们乘个-1,然后再选最好的(类似于网络流的思路) 这个可以用线段树来维护,记一个区间包含左端点/ ...

  4. BZOJ4669抢夺(费用流+二分答案)

    题目描述 大战将至, 美国决定实行计划经济.美国西部总共有 N 个城市,编号 为 0 ∼ N − 1,以及 M 条道路,道路是单向的.其中城市 0 是一个大城 市,里面住着 K 个人,而城市 N − ...

  5. [SCOI2005]王室联邦(构造)

    “余”人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理. 他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个不同的城市之间有且仅有一 ...

  6. Python学习day1 初识python&环境安装

    day1 环境安装-计算机基础 环境安装参见 https://blog.csdn.net/ling_mochen/article/details/79314118 1.markdown基本语法 htt ...

  7. nc 使用实例

    nc.exe -h即可看到各参数的使用方法.基本格式:nc [-options] hostname port[s] [ports] ...nc -l -p port [options] [hostna ...

  8. Vue -- 双向过滤器去除html标签

    <div id="box"> <input type="text" v-model="msg | filterHtml"& ...

  9. P1637 三元上升子序列

    thair 好,这个naive的东西因为只有三元,很好求解.只要把每个数之前小的L[i]与之后大的R[i]求一下即可. 求两次逆序对即可.那么答案便是∑(L[i]*R[i]); 对于更高元的,胡雨菲写 ...

  10. HTTP之Content-Type

    前言:HTTP/1.1 HTTP/1.1 协议规定的 HTTP 请求方法有OPTIONS.GET.HEAD.POST.PUT.DELETE.TRACE.CONNECT 这几种. 其中 POST 一般用 ...