@xiaoziyao
2020-10-19T18:34:40.000000Z
字数 1363
阅读 1015
解题报告
CF1139E Maximize Mex解题报告:
考虑将每个社团抽象为一个点,每个能力值抽象为一个点,社团与所有它成员的能力值连边,那么我们可以用匈牙利算法来解决这个:每一次多取一个能力值,如果可以那么加一,否则当前就是最终答案。
可以不断删边(标记每一条边删掉就好了),然后用匈牙利做到,但是仍然无法通过。
考虑将删边转化为加边(时间倒流),然后不难发现是递增的。
因为是递增的,所以每一次匈牙利都可以从上一次结束的位置开始,这样我们的复杂度就优化成了。
#include<stdio.h>
#include<string.h>
const int maxn=5005,maxm=5005,maxd=5005;
int n,m,d,e,stp,ans;
int start[maxn],to[maxm],then[maxm],c[maxn],p[maxn],k[maxd],vis[maxn],match[maxn],flg[maxn],res[maxd];
inline void add(int x,int y){
then[++e]=start[x],start[x]=e,to[e]=y;
}
int dfs(int x){
for(int i=start[x];i;i=then[i]){
int y=to[i];
if(vis[y]==stp)
continue;
vis[y]=stp;
if(match[y]==-1||dfs(match[y])){
match[y]=x;
return 1;
}
}
return 0;
}
int main(){
memset(match,-1,sizeof(match));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&p[i]);
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
scanf("%d",&d);
for(int i=1;i<=d;i++){
scanf("%d",&k[i]);
flg[k[i]]=1;
}
for(int i=1;i<=n;i++)
if(flg[i]==0)
add(p[i],c[i]);
for(int i=d;i>=1;i--){
for(int j=ans;;j++){
stp++;
if(dfs(j)==0){
ans=j;
break;
}
}
res[i]=ans;
add(p[k[i]],c[k[i]]);
}
for(int i=1;i<=d;i++)
printf("%d\n",res[i]);
return 0;
}