• codeforces#1139E. Maximize Mex(逆处理,二分匹配)


    题目链接:

    http://codeforces.com/contest/1139/problem/E

    题意:

     开始有$n$个同学和$m$,每个同学有一个天赋$p_{i}$和一个俱乐部$c_{i}$,然后在$d$天里,每天早上去除一名同学$k_{i}$,每天中午在每个俱乐部选一个人组成战队。战队的战斗力是最小的不存在的天赋,例如{1,2,3,0}战斗力是4,问每天战队的战斗力最大为多少。

    数据范围:

     $1 leq m leq n leq 5000$

    $0 leq p_i < 5000$

    $1 leq c_i leq m$

    $1 leq d leq n$

    $1 leq k_i leq n$

     

    分析:

    每次减边,然后对整体二分图匹配复杂度大概是$Oleft ( n^{3} ight )$

    于是想到逆序处理,从后往前处理,逆过程就是加边,由于加边后的ans肯定是递增的,所以复杂度降成$Oleft ( n^{2} ight )$

    如果用邻接矩阵复杂度是$Oleft ( n^{3} ight )$用邻接表是$Oleft (  n^{2} ight )$,因为对于二分图这道题的边数为$n$,属于稀疏图,所以用邻接表比较合适

    ac代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=5e3+10;;
     4 int match[maxn],vis[maxn],ans[maxn],p[maxn],c[maxn],k[maxn],d,n,m;
     5 int ma[maxn][maxn],book[maxn],f[maxn],to[maxn],cnt,nex[maxn];
     6 void add(int a,int b)
     7 {
     8     cnt++;
     9     to[cnt]=b;
    10     nex[cnt]=f[a];
    11     f[a]=cnt;
    12 }
    13 bool dfs(int x)
    14 {
    15     if(vis[x])return false;
    16     vis[x]=1;
    17     for(int i=f[x]; i; i=nex[i])
    18     {
    19         int v=to[i];
    20             if(match[v]==-1||dfs(match[v]))
    21             {
    22                 match[v]=x;
    23                 return true;
    24             }
    25     }
    26     return false;
    27 }
    28 int main()
    29 {
    30     scanf("%d %d",&n,&m);
    31     for(int i=0; i<maxn; i++)match[i]=-1;
    32     for(int i=1; i<=n; i++)
    33         scanf("%d",&p[i]);
    34     for(int i=1; i<=n; i++)
    35         scanf("%d",&c[i]);
    36     scanf("%d",&d);
    37     for(int i=1; i<=d; i++)
    38     {
    39         scanf("%d",&k[i]);
    40         book[k[i]]=1;
    41     }
    42     for(int i=1; i<=n; i++)
    43         if(book[i]==0)add(p[i],c[i]);
    44 
    45     for(int i=d; i>=1; i--)
    46     {
    47         ans[i]=ans[i+1];
    48         while(1)
    49         {
    50             memset(vis,0,sizeof(vis));
    51             if(dfs(ans[i]))ans[i]++;
    52             else break;
    53         }
    54         int x=k[i];
    55         add(p[x],c[x]);
    56     }
    57     for(int i=1; i<=d; i++)
    58         printf("%d
    ",ans[i]);
    59     return 0;
    60 }
  • 相关阅读:
    Go的几种函数式编程范例
    换零钱和快速幂
    随笔不是博客
    leetcode-51
    leetcode-50
    拨号器
    简易计算器的实现
    python入门:1-100所有数的和
    python入门:输出1-10以内除去7的所有数(简)
    python入门:输出1-10以内除去7的所有数(自写)
  • 原文地址:https://www.cnblogs.com/carcar/p/10729182.html
Copyright © 2020-2023  润新知