Codeforces Round #548 (Div. 2) E 二分图匹配(新坑) or 网络流 + 反向处理

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

题意

有n个学生,m个社团,每个学生有一个\(p_i\)值,然后每个学生属于\(c_i\)社团,
有d天,每天首先随机去除一个人,然后再从每个社团挑选一个学生(假如社团没有学生就跳过这个社团),使得这些学生组成的集合的mex值最大,输入每天的mex值

题解

  • 假如这道题发现是二分图匹配就很好做
  • 左边用\(p_i\)建点,右边用\(c_i\)建点,\(p_i\)从小到达和源点连边,然后跑个二分图匹配or最大流,直到没有新的匹配,就在中间加边
  • 倒着处理,每次加边进去(技巧)

代码

#include<bits/stdc++.h>
#define MAXN 5005

using namespace std;
int n,m,i,j,link[MAXN],p[MAXN],c[MAXN],d,k[MAXN],vi[MAXN],ans[MAXN];
int del[MAXN];
vector<int>mp[MAXN];
int match(int u){
    for(auto i:mp[u]){
        if(!vi[i]){
            vi[i]=1;
            if(link[i]==-1||match(link[i])){
                link[i]=u;
                vi[i]=0;
                return 1;
            }
            vi[i]=0;
        }
    }
    return 0;
}
int main(){
    cin>>n>>m;
    memset(link,-1,sizeof(link));
    for(i=1;i<=n;i++)cin>>p[i];
    for(i=1;i<=n;i++)cin>>c[i];
    cin>>d;
    for(i=1;i<=d;i++){cin>>k[i];del[k[i]]=1;}
    for(i=1;i<=n;i++)if(!del[i]){mp[p[i]].push_back(c[i]);}
    j=0;
    for(i=d;i>=1;i--){
        int id=k[i];
        for(;j<5000;j++){
            //memset(vi,0,m*sizeof(int));
            if(!match(j))break;
        }
        ans[i]=j;
        mp[p[id]].push_back(c[id]);
    }
    for(i=1;i<=d;i++)cout<<ans[i]<<endl;
}

猜你喜欢

转载自www.cnblogs.com/VIrtu0s0/p/10631241.html
今日推荐