zoukankan      html  css  js  c++  java
  • HDU 3335

    http://acm.hdu.edu.cn/showproblem.php?pid=3335

    题意:在给出的n个数中找出一个集合,使得其中的数互不整除,求该集合最大的元素数量

    首先要对输入的数去重,输入的数是64位的,开始没用__int64坑了好久

    一上来我以为是求二分图最大独立集,利用相反的关系建边(整除即连边),再用n去减,这样发现没过样例(因为拆点了,求得的最大匹配数要除以二),想了下发现这个解法的bug,用最大独立集求出来的互不整除的最多元素每两个之间关系是双向的,相互不整除,a不整除b并且b不整除a。但是题目的互不整除是单向的,a%b和b%a有一个为0就行。举个例子 1 2这组数,题目中不能放在一组,但是用最大独立集算,这两个就会放在一起。

    接着去搜解题报告,发现能解释的不多,都是直接给出结论的,好不容易找到一篇

    http://blog.sina.com.cn/s/blog_717d944e0100qxl0.html

    元素互不整除的集合最大数量 由Dilworth's定理得到一个等价问题:用最少的划分,每个划分集合两两可以整除

    后面那个问题确实可以转化为最小路径覆盖,即把每个数看做点,整除关系看做边

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <map>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    
    typedef __int64 ll;
    
    struct node{
        int s,t,nxt ; 
    }e[100005] ;
    int k,m,n,head[505],cnt,match[505],vis[505] ;
    int find(int s)
    {
        for(int i=head[s] ;i!=-1 ;i=e[i].nxt)
        {
            int tt=e[i].t ;
            if(!vis[tt])
            {
                vis[tt]=1 ;
                if(match[tt]==-1 || find(match[tt]))
                {
                    match[tt]=s ;
                    return 1 ;
                }
            }
        }
        return 0 ;
    }
    int max_match()
    {
        int ans=0 ;
        memset(match,-1,sizeof(match)) ;
        for(int i=1 ;i<=n ;i++)
        {
            memset(vis,0,sizeof(vis)) ;
            ans+=find(i);
        }
        return ans;
    }
    void add(int s,int t) {e[cnt].s=s ;e[cnt].t=t ;e[cnt].nxt=head[s] ;head[s]=cnt++ ;}
    
    ll a[1005],b[1005];
    
    void read_graph()
    {
        memset(head,-1,sizeof(head)) ;
        cnt=0 ;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(i==j)continue;
                if(b[i]%b[j]==0)
                    add(i,j);
            }
        }
    }
    
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%I64d",&a[i]);
            }
            int st=0;
            sort(a+1,a+1+n);
            b[++st]=a[1];
            for(int i=2;i<=n;i++){
                if(a[i]!=a[i-1])b[++st]=a[i];
            }
            n=st;
            read_graph();
            printf("%d
    ",n-max_match());
        }
        return 0;
    }
    View Code
  • 相关阅读:
    php token的生成
    php使用gearman进行任务分发
    PHP调用Python接口过程中所遇到的问题
    php结合redis实现高并发下的抢购、秒杀功能
    (转)防止表单重复提交的八种简单有效的策略
    yii防止延迟用户多次点击按钮重复提交数据
    mysql 几种日志
    神经网络模型模型转ONNX
    ResNet v2笔记
    ResNet论文笔记
  • 原文地址:https://www.cnblogs.com/xiaohongmao/p/4115860.html
Copyright © 2011-2022 走看看