BZOJ5251 八省联考2018劈配(网络流)
劈配,匹配,网络流。那么考虑怎么跑网络流。
先看第一问。首先套路的建出超源超汇。不用想也知道导师向汇连容量为战队人数上限的边。特别地,给出局也建一个点,向汇连容量inf的边(似乎没有必要)。对于一个新学员,假设我们已经知道了之前的学员的最优选择,可以把之前的每名学员和可以选择的导师连边,并由源向学员连容量为1的边。然后对于该名新学员,先只连最优选择的边,如果此时跑出的最大流不等于学员数,则表明这名学员无法选择最优,那么删掉最优边(此时这些边里一定没有流量,可以通过容量改为0实现)并连上次优边,次优边还是不行的话继续,一直这样下去直到最大流等于学员数。第一问就做完了。至于复杂度,O(能过)。
然后是第二问。对于每个人可以二分答案,然后跑最大流看其是否满足。似乎需要访问网络的历史状态?可持久化网络流!这玩意似乎没法可持久化啊……那就暴力记下来呗。由于有C的限制,这里面的边不会很多。于是就做完了,O(能过)。还有一种做法是先连上该学员可以选择的边,然后从第一名开始依次把最优选择加进去跑,直到无法满足,可能会快不少。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<vector> using namespace std; int read() {int x=0,f=1;char c=getchar();while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();return x*f; } #define N 210 #define S 0 #define T 404 int test,c,n,m,b[N],s[N],p[N<<1],cnt[N],t; int cur[N<<1],d[N<<1],q[N<<1],ans,cho[N]; vector<int> a[N][N]; struct data{int to,nxt,cap,flow; }edge[N*N<<2],hisedge[N][2510]; void addedge(int x,int y,int z) {t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].cap=z,edge[t].flow=0,p[x]=t;t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].cap=0,edge[t].flow=0,p[y]=t; } void addedge(int x,int y,int cap,int flow) {t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].cap=cap,edge[t].flow=flow,p[x]=t;t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].cap=0,edge[t].flow=-flow,p[y]=t; } void init() {for (int i=1;i<=m;i++) b[i]=read();for (int i=1;i<=n;i++){for (int j=1;j<=m+1;j++)a[i][j].clear();for (int j=1;j<=m;j++){int x=read();if (x) a[i][x].push_back(j);}a[i][m+1].push_back(m+1);}for (int i=1;i<=n;i++) s[i]=read(); } bool bfs() {memset(d,255,sizeof(d));d[S]=0;int head=0,tail=1;q[1]=S;do{int x=q[++head];for (int i=p[x];~i;i=edge[i].nxt)if (d[edge[i].to]==-1&&edge[i].flow<edge[i].cap){d[edge[i].to]=d[x]+1;q[++tail]=edge[i].to;}}while (head<tail);return ~d[T]; } int work(int k,int f) {if (k==T) return f;int used=0;for (int i=cur[k];~i;i=edge[i].nxt)if (d[k]+1==d[edge[i].to]){int w=work(edge[i].to,min(f-used,edge[i].cap-edge[i].flow));edge[i].flow+=w,edge[i^1].flow-=w;if (edge[i].flow<edge[i].cap) cur[k]=i;used+=w;if (used==f) return f;}if (used==0) d[k]=-1;return used; } void dinic() {while (bfs()){memcpy(cur,p,sizeof(p));ans+=work(S,N);} } int main() { #ifndef ONLINE_JUDGEfreopen("bzoj5251.in","r",stdin);freopen("bzoj5251.out","w",stdout);const char LL[]="%I64d"; #elseconst char LL[]="%lld"; #endiftest=read(),c=read();while (test--){n=read(),m=read();t=-1;memset(p,255,sizeof(p));memset(cnt,0,sizeof(cnt));init();for (int i=1;i<=m;i++) addedge(n+i,T,b[i]);addedge(n+m+1,T,N);for (int j=0;j<=t;j+=2)if (edge[j].cap) hisedge[0][++cnt[0]]=edge[j],hisedge[0][cnt[0]].nxt=edge[j^1].to;ans=0;for (int i=1;i<=n;i++){addedge(S,i,1);for (int j=1;j<=m+1;j++){int tmp=t;for (int k=0;k<a[i][j].size();k++)addedge(i,n+a[i][j][k],1);dinic();if (ans==i) {cho[i]=j;break;}for (int k=tmp+1;k<=t;k+=2) edge[k].cap=0;}for (int j=0;j<=t;j+=2)if (edge[j].cap) hisedge[i][++cnt[i]]=edge[j],hisedge[i][cnt[i]].nxt=edge[j^1].to;}/*for (int i=0;i<=n;i++){for (int j=1;j<=cnt[i];j++)cout<<hisedge[i][j].nxt<<' '<<hisedge[i][j].to<<' '<<hisedge[i][j].cap<<' '<<hisedge[i][j].flow<<endl;cout<<endl;}*/for (int i=1;i<=n;i++) printf("%d ",cho[i]);cout<<endl;for (int i=1;i<=n;i++){int l=0,r=i-1,add=-1;while (l<=r){int mid=l+r>>1;memset(p,255,sizeof(p));t=-1;addedge(S,i,1);for (int j=1;j<=s[i];j++)for (int k=0;k<a[i][j].size();k++)addedge(i,n+a[i][j][k],1);for (int j=1;j<=cnt[mid];j++)addedge(hisedge[mid][j].nxt,hisedge[mid][j].to,hisedge[mid][j].cap,hisedge[mid][j].flow);ans=0;dinic();if (!ans) r=mid-1;else l=mid+1,add=mid;}printf("%d ",i-add-1);}cout<<endl;}return 0; }
转载于:https://www.cnblogs.com/Gloid/p/9428149.html
BZOJ5251 八省联考2018劈配(网络流)相关推荐
- [八省联考2018]劈配
[八省联考2018]劈配 并不难的一道题,甚至比一双木棋还容易一些 关键点就是一个:怎么处理"最优结果",即总体字典序最小 显然要反悔.匹配问题反悔套路就多了 法一: 变形匈牙利算 ...
- [八省联考2018]劈配 (匈牙利)
description 一年一度的综艺节目<中国新代码>又开始了.Zayid 从小就梦想成为一名程序员,他觉得这是一个展示自己的舞台,于是他毫不犹豫地报名了. 轻车熟路的 Zayid 顺利 ...
- 洛谷 4382 [八省联考2018]劈配——二分图匹配
题目:https://www.luogu.org/problemnew/show/P4382 原本想着网络流.不过看了一番题解发现二分图匹配也行. 原本想着第一问也二分,不过看了一番题解发现一档一档地 ...
- BZOJ5251:[九省联考2018]劈配——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5251 https://loj.ac/problem/2477 <-可以看数据 https: ...
- LuoguP4383 [八省联考2018]林克卡特树lct
LuoguP4383 [八省联考2018]林克卡特树lct https://www.luogu.org/problemnew/show/P4383 分析: 题意等价于选择\(K\)条点不相交的链,使得 ...
- luogu4383 bzoj5252[八省联考2018]林克卡特树lct
** [八省联考2018]林克卡特树lct** luogu bzoj 分析 很神仙的一道wqs二分.是真的不会切>-< 如果已经切完了,最优秀的方案就是每个联通块搞直径然后连起来一定是最优 ...
- P4383 [八省联考2018]林克卡特树(树形dp+wqs二分)
[八省联考2018]林克卡特树 题目大意:给定一棵有负权边的树,现在必须恰好删去 k k k条边,并加上恰好 k k k条权值为 0 0 0的边,要求最大化它的直径长度. 首先考虑删去 K K K条边 ...
- 洛谷P4383 [八省联考2018]林克卡特树lct(DP凸优化/wqs二分)
题目描述 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战. 游戏中有一个叫做"LC ...
- dp凸优化/wqs二分学习笔记(洛谷4383 [八省联考2018]林克卡特树lct)
qwq 安利一个凸优化讲的比较好的博客 https://www.cnblogs.com/Gloid/p/9433783.html 但是他的暴力部分略微有点问题 qwq 我还是详细的讲一下这个题+这个知 ...
最新文章
- windows2003前言
- java 调用父级方法_java子类调用父类的方法中包含子类重写的实例方法
- 大数据时代的新型数据库 — 图数据库 Neo4j 的应用
- php echarts 两条曲线图,使用laravel和ECharts实现折线图效果的例子
- mysql5.7.32 win7_拯救10年前老爷机:C盘不到3G的Win7官方精简版amp;俄大神精简版分享...
- 论文翻译 基于R-FCN的物体检测
- java广告无限点击_什么是互联网广告,互联网广告的投放形式都有哪些?
- 计算机辅助设计源程序,计算机辅助设计(插值法程序).doc
- BZOJ2157旅游——树链剖分+线段树
- 如何用Camtasia给视频添加马赛克?
- javascript 分割字符串
- 大奖赛现场统分。已知某大奖赛有n个选手参赛,m(m2)个评委为参赛选手评分(最高10分,最低0分)。统分规则为:在每个选手的m个得分中,去掉一个最高分和一个最低平 每日一题--2020049--
- [创业-18]:财务报表之资产负债表
- 计算机开机出现alert,开机提示alert! cover was previously removed(主机盖被移动)
- IT经济合同的工程量清单计价技巧
- android个人记账本的实验报告,(会计登记账簿实验报告.doc
- 下拉推荐在 Shopee Chatbot 中的探索和实践
- 【Vegas原创】用vs2005调试wsf(jbs,vbs)
- 网易云易盾关于极验所述问题的致歉和说明
- GC433TR4模块性能超穿墙王SI4432无线收发模块
热门文章
- Vue学习笔记(三) —— 前后端交互
- Python元组,列表,解构和循环
- 在C#中有效地使用列表作为字典键
- VS Code 翻译插件
- ML.NET 1.3.1 发布,.NET 跨平台机器学习框架
- hive后台启动_数据仓库组件:Hive环境搭建和基础用法
- 顶岗实习周记java方向_JAVA软件开发——顶岗实习周记25篇.doc
- typora绑定github博客_零基础搭建个人博客
- 物权法全文内容有哪些呢-广告外链_合肥SEO优化小编告诉您网站外链优化方法大全...
- 数据库主键从某个值开始自增