LOJ526「LibreOJ β Round #4」子集

题目
算是比较裸的题吧。
首先我们把符合要求的\((i,j)\)建一条边,那么我们要求的就是最大团。
转化为补图的最小独立集。
然后我们来证明补图是一个二分图。
\((u,v)\)有边\(\Leftrightarrow(u,v)=1\wedge(u+1,v+1)=1\)
那么\(u,v\)的奇偶性显然不能相同,所以我们可以把这个图的点集按权值分为奇和偶两个部分。
然后再利用二分图的最大独立集等于最大匹配数,跑一遍二分图匹配就行了。

#include<cstdio>
#include<vector>
#define ll long long
#define pi pair<int,int>
#define pb push_back
using namespace std;
const int N=507;
ll read(){ll x;scanf("%lld",&x);return x;}
ll gcd(ll n,ll m){return !m? n:gcd(m,n%m);}
int n,T,match[N],vis[N];vector<ll>vec[2];vector<int>E[N];
int dfs(int u)
{
    for(int v:E[u]) if(vis[v]^T) if(vis[v]=T,(!match[v]||dfs(match[v]))) return match[v]=u;
    return 0;
}
int main()
{
    n=read();int ans=0;
    for(int i=1;i<=n;++i) {ll x=read();vec[x&1].pb(x);}
    for(int i=0,j;i<(int)vec[0].size();++i) for(j=0;j<(int)vec[1].size();++j) if(gcd(vec[0][i],vec[1][j])==1&&gcd(vec[0][i]+1,vec[1][j]+1)==1) E[i+1].pb(j+1);
    for(int i=1;i<=(int)vec[0].size();++i) if(++T,dfs(i)) ++ans;
    return !printf("%d",n-ans);
}
posted @ 2019-11-24 20:44  Shiina_Mashiro  阅读(193)  评论(0编辑  收藏  举报