luogu P4382 [九省联考2018]劈配
我记得我第一次做这道题的时候屁都不会qwq
先考虑第一问,暴力是依次枚举每个人,然后从高到低枚举志愿,枚举导师,能选就选.但是可以发现前面的人选的导师可能会导致后面的人本来可以选到这个志愿,但是不能选.这个问题是不是有点眼熟?你可以理解成二分图匹配问题,就是对于每个人,枚举志愿,然后把这个志愿对应的一些导师连边,如果跑匹配能跑出来那么他就是这个志愿,否则撤销刚才的操作
第二问类似,暴力枚举某个人到了前面的哪一名,然后把前面其他人在第一问中的方案的图先建好,然后把对应志愿\(\le s_i\)的导师加入图,如果有那个人能匹配上那么就可以前进到这一名,还要记得撤销.做的时候可以先枚举后面的人到的名次,然后枚举人,这样前面的人的图可以快速建出来.每个人的答案是当前名次-最大的合法名次
实现用的是网络流,因为比较方便退流以及撤销边,开个栈栈序撤销.注意及时撤销
// luogu-judger-enable-o2
//qwqwq
#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define db double
using namespace std;
const int N=200+10,M=3e5+10;
const db eps=1e-4;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int to[M],nt[M],c[M],hd[N<<1],tot=1;
void add(int x,int y,int z)
{
++tot,to[tot]=y,nt[tot]=hd[x],c[tot]=z,hd[x]=tot;
++tot,to[tot]=x,nt[tot]=hd[y],c[tot]=0,hd[y]=tot;
}
void wd(){hd[to[tot^1]]=nt[tot],--tot;}
int stk[M<<3][2],tp;
void wdflow()
{
while(tp)
{
int i=stk[tp][0],dt=stk[tp][1];
c[i]+=dt,c[i^1]-=dt;
--tp;
}
}
int ps,pt,lv[N<<1];
queue<int> q;
bool bfs()
{
for(int i=0;i<=pt;++i) lv[i]=0;
lv[ps]=1,q.push(ps);
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(c[i]>0&&!lv[y])
{
lv[y]=lv[x]+1;
q.push(y);
}
}
}
return lv[pt];
}
int dfs(int x,int fw)
{
if(x==pt) return fw;
int an=0;
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(c[i]>0&&lv[y]==lv[x]+1)
{
int dt=dfs(y,min(fw,c[i]));
stk[++tp][0]=i,stk[tp][1]=dt;
c[i]-=dt,c[i^1]+=dt;
fw-=dt,an+=dt;
if(!fw) break;
}
}
return an;
}
int dinic()
{
int an=0,dt;
while(bfs())
while((dt=dfs(ps,2333333)))
an+=dt;
return an;
}
int n,m,an[N],a2[N],b[N],s[N];
vector<int> dls[N][N];
vector<int>::iterator it;
int main()
{
int T=rd();
rd();
while(T--)
{
n=rd(),m=rd();
ps=0,pt=n+m+1;
for(int i=0;i<=pt;++i) hd[i]=0;
tot=1;
for(int i=1;i<=n;++i)
{
add(ps,i+m,1);
for(int j=1;j<=m+1;++j) dls[i][j].clear();
}
for(int i=1;i<=m;++i) add(i,pt,b[i]=rd());
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
dls[i][rd()].push_back(j);
for(int i=1;i<=n;++i)
{
an[i]=m+1;
for(int j=1;j<=m;++j)
{
if(!dls[i][j].size()) continue;
int latt=tot;
for(it=dls[i][j].begin();it!=dls[i][j].end();++it)
add(i+m,*it,1);
tp=0;
if(dinic()){an[i]=j;break;}
wdflow();
while(tot>latt) wd();
}
printf("%d ",an[i]);
}
puts("");
for(int i=1;i<=n;++i) s[i]=rd();
for(int i=0;i<=pt;++i) hd[i]=0;
tot=1;
for(int i=1;i<=n;++i) add(ps,i+m,1),a2[i]=0;
for(int i=1;i<=m;++i) add(i,pt,b[i]);
for(int i=1;i<=n;++i)
{
for(int j=i;j<=n;++j)
{
if(an[j]<=s[j]){a2[j]=j;continue;}
int latt=tot;
for(int k=1;k<=s[j];++k)
{
if(!dls[j][k].size()) continue;
for(it=dls[j][k].begin();it!=dls[j][k].end();++it)
add(j+m,*it,1);
}
tp=0;
if(dinic()) a2[j]=i;
wdflow();
while(tot>latt) wd();
}
for(it=dls[i][an[i]].begin();it!=dls[i][an[i]].end();++it)
add(i+m,*it,1);
tp=0,dinic();
}
for(int i=1;i<=n;++i) printf("%d ",i-a2[i]);
puts("");
}
return 0;
}
luogu P4382 [九省联考2018]劈配的更多相关文章
- [BZOJ5251][九省联考2018]劈配(网络流)
5251: [2018多省省队联测]劈配 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 33 Solved: 22[Submit][Status][ ...
- BZOJ5251:[九省联考2018]劈配——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5251 https://loj.ac/problem/2477 <-可以看数据 https: ...
- 洛谷P4382 [八省联考2018]劈配(网络流,二分答案)
洛谷题目传送门 说不定比官方sol里的某理论最优算法还优秀一点? 所以\(n,m\)说不定可以出到\(1000\)? 无所谓啦,反正是个得分题.Orz良心出题人,暴力有70分2333 思路分析 正解的 ...
- P4382 [八省联考2018]劈配
题目链接 题意分析 受到了\(olinr\ \ julao\)的影响 写了匈牙利算法 首先 我们对于每一个人 从高到低枚举志愿 如果当前志愿的老师有剩余的话 那么我们就选 否则的话 我们看看谁的那个志 ...
- [luogu] P4364 [九省联考2018]IIIDX(贪心)
P4364 [九省联考2018]IIIDX 题目背景 Osu 听过没?那是Konano 最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在,他在世界知名游戏公司KONMAI ...
- BZOJ5251 八省联考2018劈配(网络流)
劈配,匹配,网络流.那么考虑怎么跑网络流. 先看第一问.首先套路的建出超源超汇.不用想也知道导师向汇连容量为战队人数上限的边.特别地,给出局也建一个点,向汇连容量inf的边(似乎没有必要).对于一个新 ...
- luogu P4365 [九省联考2018]秘密袭击coat
luogu 这里不妨考虑每个点的贡献,即求出每个点在多少个联通块中为第\(k\)大的(这里权值相同的可以按任意顺序排大小),然后答案为所有点权值\(*\)上面求的东西之和 把比这个点大的点看成\(1\ ...
- luogu P4363 [九省联考2018]一双木棋chess
传送门 对抗搜索都不会,我真是菜死了qwq 首先根据题目条件,可以发现从上到下每一行的棋子数是单调不增的,然后n m都比较小,如果把状态搜出来,可以发现合法状态并不多,所以可以用一个11进制数表示状态 ...
- 【题解】Luogu P4363 [九省联考2018]一双木棋chess
原题传送门 这道题珂以轮廓线dp解决 经过推导,我们珂以发现下一行的棋子比上一行的棋子少(或等于),而且每一行中的棋子都是从左向右依次排列(从头开始,中间没有空隙) 所以每下完一步棋,棋盘的一部分是有 ...
随机推荐
- Android_(控件)Chronometer计时器
Android Chronometer(计时器) 继承TextView,显示的是某个时间点开始以及之后的时间增加 运行截图 程序结构 package com.example.administrator ...
- Struts2理解?
(1)Struts2是一个基于MVC设计模式的Web应用框架,在MVC设计模式中Struts2作为控制器(Controller)来建立模型与视图的数据交互. Struts 2以WebWork为核心,采 ...
- forms authentication原理
细说ASP.NET Forms身份认证 asp.net 登陆验证 Form表单验证的3种方式 Understanding and Implementing ASP.NET Custom Forms A ...
- 数据库-MongoDb
*本文总结下使用Mongodb遇到的问题: 1. 安装完MongoDb后先启动服务端,然后再启动客户端: 直接上图: 注意点:mongod.exe :是用来连接到mongo数据库服务器的,即服务器端. ...
- Use an Excel RTD Server with DCOM
费好大劲找到的文章,留存. Use an Excel RTD Server with DCOM 如何使用DCOM的Excel RTD服务器 Microsoft Office Excel 2007,Mi ...
- XPath2Doc,一个半自动采集网页生成Word Docx文件的工具,带企查查和天眼查模板
原始出处:https://www.cnblogs.com/Charltsing/p/XPath2Doc.html 很多人需要从网站采集一些数据填写Word模板,手工操作费时费力还容易出错,所以我给朋友 ...
- Netem参数说明
Netem参数说明 本文主要内容来自Linux基金会Wiki网站Netem文档,点击这里访问原文 netem通过模拟广域网的特性为测试协议提供网络仿真功能.当前版本模拟可变延迟,丢失,重复和重新排序. ...
- ControlTemplate in WPF —— Button
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x ...
- 慕课网_Java入门第二季
第1章 类和对象 1-1 什么是类和对象 (07:36) 1-2 如何定义 Java 中的类 (07:18) 1-3 如何使用 Java 中的对象 (04:45) 1-4 练习题 1-5 Java 中 ...
- 用edoc2实现上传和下载
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import org.apache.http.Htt ...