直接网络流模拟即可AC。
可持久化+暴力=90分,
可持久化+二分=30分,
暴力加边+二分=100分。
我也很无奈啊。
Ivan便涨红了脸,额上的青筋条条绽出,争辩道,“memcpy也是可持久化……memcpy!……OIer的事,当然是可持久化!”接连便是难懂的话,什么“可持久化无旋Treap套线段树启发式合并”,什么“暴力踩正解”之类,引得众人都哄笑起来。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#define N 205
#define inf 0x7fffffff
using namespace std;
struct FLOW{
int e,head[];
struct edge{
int u,v,f,of,next;
}ed[N*N<<];
void add(int u,int v,int f){
ed[e].u=u;ed[e].v=v;ed[e].f=f;ed[e].next=head[u];head[u]=e++;
ed[e].u=v;ed[e].v=u;ed[e].f=;ed[e].next=head[v];head[v]=e++;
}
int dep[],S,T;
bool bfs(){
memset(dep,,sizeof dep);
queue<int> q;
q.push(S);dep[S]=;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=head[x];i;i=ed[i].next){
if(ed[i].f&&!dep[ed[i].v]){
dep[ed[i].v]=dep[x]+;
if(ed[i].v==T)return ;
q.push(ed[i].v);
}
}
}
return ;
}
int dfs(int x,int f){
if(x==T||!f)return f;
int ans=;
for(int i=head[x];i;i=ed[i].next){
int v=ed[i].v;
if(ed[i].f&&dep[v]==dep[x]+){
int nxt=dfs(v,min(f,ed[i].f));
ans+=nxt;f-=nxt;ed[i].f-=nxt;ed[i^].f+=nxt;
if(!f)break;
}
}
if(!ans)dep[x]=-;
return ans;
}
int dinic(){
int ans=;
while(bfs())ans+=dfs(S,inf);
return ans;
}
void init(){
memset(head,,sizeof head);
e=;
}
}F,G,NF;
int T,C,n,m,b[N],dr[N],pos[N][N],g[N][N],bo[N],ans[N],pp[N],sum[N];
vector <int> V[N];
int O;
bool cmp(int a,int b){
return g[O][a]<g[O][b];
}
bool check(int x,int i){
NF.init();
NF.S=n+m+;NF.T=n+m+;
for(int j=;j<=m;j++)NF.add(n+j,NF.T,b[j]);
for(int j=;j<=x;j++){
NF.add(NF.S,j,);
for(int k=;k<V[j].size();k++)
NF.add(j,n+V[j][k],);
}
NF.add(NF.S,i,);
for(int k=;k<=m&&g[i][pos[i][k]]<=dr[i];k++)NF.add(i,n+pos[i][k],);
if(NF.dinic()==sum[x]+)return ;
return ;
}
int main(){
scanf("%d%d",&T,&C);
while(T--){
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)scanf("%d",&b[i]);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
pos[i][j]=j;
scanf("%d",&g[i][j]);
if(!g[i][j])g[i][j]=;
}
O=i;
sort(pos[i]+,pos[i]+m+,cmp);
}
for(int i=;i<=n;i++)scanf("%d",&dr[i]);
F.init();
F.S=n+m+;F.T=F.S+;
for(int i=;i<=n;i++)F.add(F.S,i,);
for(int i=;i<=m;i++)F.add(n+i,F.T,b[i]);
G=F;
for(int i=;i<=n;i++)V[i].clear();
memset(pp,,sizeof pp);
memset(ans,,sizeof ans);
memset(bo,,sizeof bo);
for(int i=;i<=n;i++){
for(int j=,k=;j<=m;j=++k){
if(g[i][pos[i][j]]==)break;
while(k<m&&g[i][pos[i][k+]]==g[i][pos[i][j]])k++;
for(int l=j;l<=k;l++)F.add(i,n+pos[i][l],);
if(F.bfs()&&F.dfs(F.S,inf)==){
pp[i]=g[i][pos[i][j]];
for(int l=j;l<=k;l++)V[i].push_back(pos[i][l]);
break;
}
}
if(!pp[i])pp[i]=m+,sum[i]=sum[i-];
else{
for(int j=;j<V[i].size();j++)
G.add(i,n+V[i][j],);
G.bfs();G.dfs(G.S,inf);
sum[i]=sum[i-]+;
}
F=G;
}
for(int i=;i<=n;i++){
if(g[i][pos[i][]]>dr[i]){ans[i]=i;continue;}
int l=,r=i-,mid,fin=;
while(l<=r){
mid=(l+r)>>;
if(check(mid,i))fin=mid,l=mid+;
else r=mid-;
}
ans[i]=i-r-;
}
for(int i=;i<=n;i++)printf("%d%c",pp[i],((i==n)?'\n':' '));
for(int i=;i<=n;i++)printf("%d%c",ans[i],((i==n)?'\n':' '));
}
return ;
}