codeforces1139E Maximize Mex 二分图匹配

题目传送门

题意:给出n个人,m个社团,每个人都有一个标号,一个能力值,并且属于一个社团,第i天的凌晨,第$k_i$个人会离开。每天每个社团最多派一个人出来参加活动。派出的人的能力值集合为S,求每天$MEX{S}$的最大值。

思路:这道题正着删人和倒着加人是一样的,并且很容易看出是二分图的题,加边显然要比删边容易操作,所以我们要倒着考虑。

  只要想到了倒着考虑,剩下的就比较好想了。由于从小到大的能力值是必选的,我们把能力值作为左边的节点,社团作为右边的节点。每增加一个人就增加对应的边,每次匹配的时候上次的答案开始匹配,匹配到不能匹配位置,就是当前的答案了。由于二分图的特殊性,将当前这个点匹配了,肯定不会使之前的点变成失配点。

  要注意的是,这里人的能力值最低是0,所以$match[x]=0$也是一个合法匹配,而大部分匈牙利算法的模板中都使用$match[x]==0$来作为有没有匹配过的判断条件,要注意修改。

#pragma GCC optimize (2)
#pragma G++ optimize (2)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#include<cstdio>
#include<vector>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,b,a) for(int i=b;i>=a;i--)
#define clr(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pii pair<int,int >
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
ll rd()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int maxn=5010;
const ll mod=1e9+7;
int n,m;
vector<int >ve[maxn];
int match[maxn],vis[maxn];
bool dfs(int u){
    for(auto &v:ve[u]){
        if(!vis[v]){
            vis[v]=1;
            if(match[v]==-1||dfs(match[v])){
                match[v]=u;
                return true;
            }
        }
    }
    return false;
}
struct node{
    int pos,val;
}arr[maxn];
int k[maxn],num[maxn],ans[maxn];
int main(){
    cin>>n>>m;
    rep(i,1,n){
        arr[i].val=rd();
    }
    rep(i,1,n){
        arr[i].pos=rd();
    }
    int d;
    cin>>d;
    rep(i,1,d){
        k[i]=rd();
        num[k[i]]=1;
    }
    clr(match,-1);
    rep(i,1,n){
        if(!num[i]){
            ve[arr[i].val].push_back(arr[i].pos);
        }
    }
    int pos=0;
    dep(i,d,1){
        while(1){
            clr(vis,0);
            if(dfs(pos)){
                pos++;
            }else{
                break;
            }
        }
        ans[i]=pos;
        ve[arr[k[i]].val].push_back(arr[k[i]].pos);
    }
    rep(i,1,d){
        printf("%d\n",ans[i]);
    }
}

 

posted @ 2019-10-08 18:06  光芒万丈小太阳  阅读(255)  评论(0编辑  收藏  举报