劈配,匹配,网络流。那么考虑怎么跑网络流。

  先看第一问。首先套路的建出超源超汇。不用想也知道导师向汇连容量为战队人数上限的边。特别地,给出局也建一个点,向汇连容量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劈配(网络流)相关推荐

  1. [八省联考2018]劈配

    [八省联考2018]劈配 并不难的一道题,甚至比一双木棋还容易一些 关键点就是一个:怎么处理"最优结果",即总体字典序最小 显然要反悔.匹配问题反悔套路就多了 法一: 变形匈牙利算 ...

  2. [八省联考2018]劈配 (匈牙利)

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

  3. 洛谷 4382 [八省联考2018]劈配——二分图匹配

    题目:https://www.luogu.org/problemnew/show/P4382 原本想着网络流.不过看了一番题解发现二分图匹配也行. 原本想着第一问也二分,不过看了一番题解发现一档一档地 ...

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

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

  5. LuoguP4383 [八省联考2018]林克卡特树lct

    LuoguP4383 [八省联考2018]林克卡特树lct https://www.luogu.org/problemnew/show/P4383 分析: 题意等价于选择\(K\)条点不相交的链,使得 ...

  6. luogu4383 bzoj5252[八省联考2018]林克卡特树lct

    ** [八省联考2018]林克卡特树lct** luogu bzoj 分析 很神仙的一道wqs二分.是真的不会切>-< 如果已经切完了,最优秀的方案就是每个联通块搞直径然后连起来一定是最优 ...

  7. P4383 [八省联考2018]林克卡特树(树形dp+wqs二分)

    [八省联考2018]林克卡特树 题目大意:给定一棵有负权边的树,现在必须恰好删去 k k k条边,并加上恰好 k k k条权值为 0 0 0的边,要求最大化它的直径长度. 首先考虑删去 K K K条边 ...

  8. 洛谷P4383 [八省联考2018]林克卡特树lct(DP凸优化/wqs二分)

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

  9. dp凸优化/wqs二分学习笔记(洛谷4383 [八省联考2018]林克卡特树lct)

    qwq 安利一个凸优化讲的比较好的博客 https://www.cnblogs.com/Gloid/p/9433783.html 但是他的暴力部分略微有点问题 qwq 我还是详细的讲一下这个题+这个知 ...

最新文章

  1. windows2003前言
  2. java 调用父级方法_java子类调用父类的方法中包含子类重写的实例方法
  3. 大数据时代的新型数据库 — 图数据库 Neo4j 的应用
  4. php echarts 两条曲线图,使用laravel和ECharts实现折线图效果的例子
  5. mysql5.7.32 win7_拯救10年前老爷机:C盘不到3G的Win7官方精简版amp;俄大神精简版分享...
  6. 论文翻译 基于R-FCN的物体检测
  7. java广告无限点击_什么是互联网广告,互联网广告的投放形式都有哪些?
  8. 计算机辅助设计源程序,计算机辅助设计(插值法程序).doc
  9. BZOJ2157旅游——树链剖分+线段树
  10. 如何用Camtasia给视频添加马赛克?
  11. javascript 分割字符串
  12. 大奖赛现场统分。已知某大奖赛有n个选手参赛,m(m2)个评委为参赛选手评分(最高10分,最低0分)。统分规则为:在每个选手的m个得分中,去掉一个最高分和一个最低平 每日一题--2020049--
  13. [创业-18]:财务报表之资产负债表
  14. 计算机开机出现alert,开机提示alert! cover was previously removed(主机盖被移动)
  15. IT经济合同的工程量清单计价技巧
  16. android个人记账本的实验报告,(会计登记账簿实验报告.doc
  17. 下拉推荐在 Shopee Chatbot 中的探索和实践
  18. 【Vegas原创】用vs2005调试wsf(jbs,vbs)
  19. 网易云易盾关于极验所述问题的致歉和说明
  20. GC433TR4模块性能超穿墙王SI4432无线收发模块

热门文章

  1. Vue学习笔记(三) —— 前后端交互
  2. Python元组,列表,解构和循环
  3. 在C#中有效地使用列表作为字典键
  4. VS Code 翻译插件
  5. ML.NET 1.3.1 发布,.NET 跨平台机器学习框架
  6. hive后台启动_数据仓库组件:Hive环境搭建和基础用法
  7. 顶岗实习周记java方向_JAVA软件开发——顶岗实习周记25篇.doc
  8. typora绑定github博客_零基础搭建个人博客
  9. 物权法全文内容有哪些呢-广告外链_合肥SEO优化小编告诉您网站外链优化方法大全...
  10. 数据库主键从某个值开始自增