【BZOJ5251】【九省联考2018】—劈配(网络流)
据说匈牙利变一下跑的贼快?
反正我选择
第一次跑下来上倒数第二
嘤嘤嘤
第一问很好做
考虑依次枚举每个人,枚举每种志愿
跑网络流,看有没有流量
如果有的话显然是有满足方案的
没有最好把这一种的边给删了,因为反正以后也没有用了
第二问考虑可以二分
然后把这个人提到前面去,连边看能不能跑出来
为了方便写了个结构体存边
虽然跑得慢但代码还是清真吧
#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
return res*f;
}
const int inf=1e9;
const int M=10006;
const int N=205;
int str,des,n,m;
int T,c,mx[N],f[N],ans[N],hp[N];
vector<int> e[N][N];
struct Graph{
int adj[M],nxt[M<<1],to[M<<1],cap[M<<1],tp[M<<1],lev[M<<1],cnt;
Graph(int _cnt=1){cnt=_cnt;}
inline void init(){
memset(adj,0,sizeof(adj)),cnt=1;
}
inline void addedge(int u,int v,int w){
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,cap[cnt]=w;
nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u,cap[cnt]=0;
}
inline void deletedge(int u,int v){
adj[u]=nxt[adj[u]],cnt--;
adj[v]=nxt[adj[v]],cnt--;
}
inline bool bfs(){
memset(lev,-1,sizeof(lev));
queue<int> q;
lev[str]=0,q.push(str);
while(!q.empty()){
int u=q.front();q.pop();
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(cap[e]>0&&lev[v]==-1){
lev[v]=lev[u]+1,q.push(v);
if(v==des){
return true;
}
}
}
}
return false;
}
int dinic(int u,int flow){
if(u==des)return flow;
int res=0;
for(int &e=tp[u];e;e=nxt[e]){
int v=to[e];
if(cap[e]>0&&lev[v]==lev[u]+1){
int now=dinic(v,min(flow-res,cap[e]));
res+=now,cap[e]-=now,cap[e^1]+=now;
if(flow==res){
return res;
}
}
}
return res;
}
}G[N];
inline void solve1(){
for(int i=1;i<=n;i++){
G[i]=G[i-1];
G[i].addedge(str,i,1);
for(int j=1;j<=m;j++){
for(int p=0;p<e[i][j].size();p++)
G[i].addedge(i,e[i][j][p]+n,1);
if(G[i].bfs()){
memcpy(G[i].tp,G[i].adj,sizeof(G[i].adj));
G[i].dinic(str,inf);
ans[i]=j;break;
}
for(int p=0;p<e[i][j].size();p++)
G[i].deletedge(i,e[i][j][p]+n);
}
}
for(int i=1;i<=n;i++){
if(!ans[i])ans[i]=m+1;
cout<<ans[i]<<" ";
}puts("");
}
inline bool check(int u,int pt){
Graph tg=G[pt-1];
tg.addedge(str,u,1);
for(int i=1;i<=f[u];i++)
for(int j=0;j<e[u][i].size();j++)
tg.addedge(u,e[u][i][j]+n,1);
if(tg.bfs())return 1;
else return 0;
}
inline void solve2(){
for(int i=1;i<=n;i++){
if(ans[i]<=f[i])continue;
hp[i]=inf;
int l=1,r=i-1;
while(l<=r){
int mid=(l+r)>>1;
if(check(i,mid))hp[i]=mid,l=mid+1;
else r=mid-1;
}
if(hp[i]&&hp[i]!=inf)hp[i]=i-hp[i];
}
for(int i=1;i<=n;i++)cout<<((hp[i]==inf)?(i):(hp[i]))<<" ";
puts("");
}
inline void clear(){
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
e[i][j].clear();
memset(ans,0,sizeof(ans));
memset(hp,0,sizeof(hp));
G[0].init();
}
inline void solve(){
clear();
n=read(),m=read();
str=n+m+1,des=str+1;
for(int i=1;i<=m;i++){
mx[i]=read();
G[0].addedge(i+n,des,mx[i]);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
int p=read();if(p)
e[i][p].push_back(j);
}
for(int i=1;i<=n;i++)f[i]=read();
solve1(),solve2();
}
int main(){
T=read(),c=read();
while(T--)solve();
}