zoukankan      html  css  js  c++  java
  • zoj3988(自己集合和自己集合匹配)

    题:https://zoj.pintia.cn/problem-sets/91827364500/problems/91827370128

    题意:给定n个数(n<=3e3)俩者能匹配的充分必要条件未俩者之和为质数,求至多匹配完k对后各个数所属下标的并集最大是多少;

    分析:二分图直接匈牙利算法搞起,主要k限制,那就判断匹配数和k之间关系;

       若ans<=k,那么匹配数足以贪心地输出2*k;

       否则看剩下有多少个,1个就有一个贡献,因为经过最大匹配后另一个一定被匹配完了;

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=1e9+7;
    const int M=3e3+5;
    typedef long long ll;
    #define pb push_back
    
    const int N=2e6+6;
    const int inf=0x3f3f3f3f;
    int mp[M],vis[M],a[M];
    int n;
    int prime[N];
    vector<int>g[M];
    void init(){
        for(int i=2;i<N;i++){
            if(!prime[i]){
                for(int j=i+i;j<N;j+=i)
                    prime[j]=1;
            }
        }
    }
    int dfs(int u){
        vis[u]=1;
        for(auto v:g[u]){
            if(!vis[v]){
                vis[v]=1;
                if(mp[v]==-1||dfs(mp[v])){
                    mp[v]=u;
                    mp[u]=v;
                    return 1;
                }
            }
        }
        return 0;
    }
    int xiong(){
        int res=0;
        for(int i=1;i<=n;i++)
            if(mp[i]==-1){///一般的匈牙利算法不用这句,这题加代表选过了不能再选,只能从未选过的开始选
                memset(vis,0,sizeof(vis));
                res+=dfs(i);
            }
        return res;
    }
    int main(){
        int T;
        scanf("%d",&T);
        init();
        while(T--){
            int k;
            scanf("%d%d",&n,&k);
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]),mp[i]=0,g[i].clear();
            int sum=0;
            for(int i=1;i<=n;i++){
                for(int j=i+1;j<=n;j++)
                    if(!prime[a[i]+a[j]]){
                        ///cout<<i<<"  "<<j<<endl;
                        g[i].pb(j),g[j].pb(i);
                        mp[i]=-1,mp[j]=-1;
                    }
            }
    
            int ans=xiong();
            if(ans>=k){ printf("%d
    ",k*2); }
            else{
                int leave=0;
                for(int i=1;i<=n;i++)
                    if(mp[i]==-1) leave++;
                printf("%d
    ",2*ans+min(k-ans,leave));
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    【阿里的感悟】质量该如何做? .(转载)
    java linux 配置环境
    Spring Bean属性绑定Bean返回值
    Spring BeanNameAutoProxyCreator 与 ProxyFactoryBean
    Spring Aop之(二)Aop 切面声明和通知
    Ubuntu开机自动启动Script
    转战博客园!
    linux 系统管理11 ——系统安全及应用
    linux awk
    Rsync数据同步工具
  • 原文地址:https://www.cnblogs.com/starve/p/13859374.html
Copyright © 2011-2022 走看看