• 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
    ",ans[i]);
        }
    }
  • 相关阅读:
    【数据结构】平衡二叉树之AVL树
    【数据结构】二叉排序树BST
    【数据结构】二叉树
    【算法】堆排序
    【数据结构】堆
    第五百八十一天 how can I 坚持
    第五百八十天 how can I 坚持
    第五百七十八、九天 how can I 坚持
    第五百七十七天 how can I 坚持
    第五百七十五、六天 how can I 坚持
  • 原文地址:https://www.cnblogs.com/mountaink/p/11637024.html
Copyright © 2020-2023  润新知