zoukankan      html  css  js  c++  java
  • #二分图匹配#洛谷 5771 [JSOI2016]反质数序列

    题目

    给出 (n) 个正整数,问最大的子集使得任意两个数的和都不是质数
    (nleq 3*10^3)


    分析

    如果把两个数的和为质数连边,等价于求最大独立集。

    由于只有偶数加奇数才可能产生质数(1+1除外),所以可以根据其奇偶性分成两部分,

    那求一个二分图匹配即可,注意最大独立集最多只能有一个1


    代码

    #include <cstdio>
    #include <cctype>
    #define rr register
    using namespace std;
    const int N=3011,M=200011; struct node{int y,next;}e[N*N/4];
    int v[M],prime[M],Cnt,flag,odd[N],even[N],link[N],upd,as[N],et,ans;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline void Pro(int n){
    	v[1]=1;
    	for (rr int i=2;i<=n;++i){
    		if (!v[i]) prime[++Cnt]=i;
    		for (rr int j=1;j<=Cnt&&prime[j]<=n/i;++j){
    			v[i*prime[j]]=1;
    			if (i%prime[j]==0) break;
    		}
    	}
    }
    inline bool match(int x){
    	for (rr int i=as[x];i;i=e[i].next)
    	if (v[e[i].y]!=upd){
    		rr int q=link[e[i].y];
    		link[e[i].y]=x,v[e[i].y]=upd;
    		if (!q||match(q)) return 1;
    		link[e[i].y]=q;
    	}
    	return 0;
    }
    signed main(){
    	Pro(200000),flag=upd=1;
    	for (rr int T=iut();T;--T){
    		rr int x=iut();
    		if (x%2==0) even[++even[0]]=x;
    		    else if (x>1) odd[++odd[0]]=x;
    		        else if (x==1&&flag) flag=0,odd[++odd[0]]=x;
    	}
    	for (rr int i=1;i<=odd[0];++i)
    	for (rr int j=1;j<=even[0];++j)
    	if (!v[odd[i]+even[j]])
    		e[++et]=(node){j,as[i]},as[i]=et;
    	for (rr int i=1;i<=odd[0];++i) ++upd,ans+=match(i);
    	return !printf("%d",odd[0]+even[0]-ans);
    } 
    
  • 相关阅读:
    CentOS+Nginx+PHP+MySQL详细配置(图解)
    linux下MySQL安装登录及操作
    hdu 1059 多重背包
    hdu 1754 单点更新
    poj 3264 RMQ 水题
    hdu 1114 基础完全背包
    hdu 3466 排序01背包
    poj 2923 状压dp+01背包
    hdu 2639 第k大01背包
    hdu 2184 01背包变形
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/15424101.html
Copyright © 2011-2022 走看看