[关闭]
@xiaoziyao 2020-10-19T18:34:40.000000Z 字数 1363 阅读 1015

CF1139E Maximize Mex解题报告

解题报告


CF1139E Maximize Mex解题报告:

更好的阅读体验

题意

分析

考虑将每个社团抽象为一个点,每个能力值抽象为一个点,社团与所有它成员的能力值连边,那么我们可以用匈牙利算法来解决这个:每一次多取一个能力值,如果可以那么加一,否则当前就是最终答案。

可以不断删边(标记每一条边删掉就好了),然后用匈牙利做到,但是仍然无法通过。

考虑将删边转化为加边(时间倒流),然后不难发现是递增的。

因为是递增的,所以每一次匈牙利都可以从上一次结束的位置开始,这样我们的复杂度就优化成了

代码

  1. #include<stdio.h>
  2. #include<string.h>
  3. const int maxn=5005,maxm=5005,maxd=5005;
  4. int n,m,d,e,stp,ans;
  5. int start[maxn],to[maxm],then[maxm],c[maxn],p[maxn],k[maxd],vis[maxn],match[maxn],flg[maxn],res[maxd];
  6. inline void add(int x,int y){
  7. then[++e]=start[x],start[x]=e,to[e]=y;
  8. }
  9. int dfs(int x){
  10. for(int i=start[x];i;i=then[i]){
  11. int y=to[i];
  12. if(vis[y]==stp)
  13. continue;
  14. vis[y]=stp;
  15. if(match[y]==-1||dfs(match[y])){
  16. match[y]=x;
  17. return 1;
  18. }
  19. }
  20. return 0;
  21. }
  22. int main(){
  23. memset(match,-1,sizeof(match));
  24. scanf("%d%d",&n,&m);
  25. for(int i=1;i<=n;i++)
  26. scanf("%d",&p[i]);
  27. for(int i=1;i<=n;i++)
  28. scanf("%d",&c[i]);
  29. scanf("%d",&d);
  30. for(int i=1;i<=d;i++){
  31. scanf("%d",&k[i]);
  32. flg[k[i]]=1;
  33. }
  34. for(int i=1;i<=n;i++)
  35. if(flg[i]==0)
  36. add(p[i],c[i]);
  37. for(int i=d;i>=1;i--){
  38. for(int j=ans;;j++){
  39. stp++;
  40. if(dfs(j)==0){
  41. ans=j;
  42. break;
  43. }
  44. }
  45. res[i]=ans;
  46. add(p[k[i]],c[k[i]]);
  47. }
  48. for(int i=1;i<=d;i++)
  49. printf("%d\n",res[i]);
  50. return 0;
  51. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注