hihocoder 1158 二分图

转化为求最大独立集

#include<bits/stdc++.h>
#define Mem(a,b) memset(a,b,sizeof(a))
#define lson root<<1
#define rson root<<1|1
#define Mid int mid=(l+r)>>1
#define FREI freopen("in.txt","r",stdin)
#define N 500100
#define ll long long
#define eps 1e-6
#define Maxn 1010
using namespace std;
vector<int>prime;
bool vis[Maxn+10];
bool mark[N];
struct edge{
    int v,next;
};
edge e[N];
int head[N],cnt,X[N],num,pre[N],used[N],a[N];
void add(int u,int v){
    e[cnt].v=v,e[cnt].next=head[u];
    head[u]=cnt++;
}
void init(){
    Mem(vis,0);
    for(int i=2;i<Maxn;i++){
        if(!vis[i]){
            prime.push_back(i);
            for(int j=i+i;j<Maxn;j+=i) vis[j]=1;
        }
    }
}
void solve(int x){
    int tmp=x;
    for(int i=0;i<prime.size()&&prime[i]*prime[i]<=x;i++){
        if(x%prime[i]==0){
            int p=prime[i];
            if(mark[tmp/p]) {
                add(tmp/p,tmp);
                add(tmp,tmp/p);
            }
            while(x%prime[i]==0) x/=prime[i];
        }
    }
    if(x>1&&mark[tmp/x]){
        add(tmp/x,tmp);
        add(tmp,tmp/x);
    }
}
void dfs1(int x,int id){
    if(id==1)
        X[num++]=x;
    for(int i=head[x];~i;i=e[i].next){
        int v=e[i].v;
        if(!used[v]) {
            used[v]=1;
            dfs1(v,-id);
        }
    }
}
void work(int n){
    Mem(used,0);
    num=0;
    for(int i=0;i<n;i++){
        if(!used[a[i]]&&head[a[i]]!=-1){
            used[a[i]]=1;
            dfs1(a[i],1);
        }
    }
}
bool dfs(int u){
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(!used[v]){
            used[v]=1;
            if(!pre[v]||dfs(pre[v])){
                pre[v]=u;
                return true;
            }

        }
    }
    return false;
}
int main() {
    //FREI;
    init();
    int cas;
    scanf("%d",&cas);
    for(int i=1;i<=cas;i++){
        Mem(mark,0);
        cnt=0;
        Mem(head,-1);
        int n;
        scanf("%d",&n);
        for(int j=0;j<n;j++){
            scanf("%d",&a[j]);
            mark[a[j]]=1;
        }
        for(int j=0;j<n;j++){
            solve(a[j]);
        }
        work(n);
        int ans=0;
        Mem(pre,0);
        for(int i=0;i<num;i++){
            Mem(used,0);
            if(dfs(X[i])) ans++;
        }
        printf("Case #%d: %d\n",i,n-ans);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值