1. 程式人生 > >Codeforces Round #548 (Div. 2) E 二分圖匹配(新坑) or 網絡流 + 反向處理

Codeforces Round #548 (Div. 2) E 二分圖匹配(新坑) or 網絡流 + 反向處理

-- cin problem fine max href fin names i++

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;
}

Codeforces Round #548 (Div. 2) E 二分圖匹配(新坑) or 網絡流 + 反向處理