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
  • 相关阅读:
    软件测试第四周--闰年问题的非法输入处理
    Edit Boxing三个盒子——等价类划分以及实现
    软件测试--等价类划分的基本概念及实际应用
    对软件测试工具的认识
    软件测试的流程及策略
    几种简单的软件测试模型
    软件开发中的白盒测试
    一种简单的软件测试工具——Visual Studio2010
    int Parse方法引发的异常
    两种软件测试框架——JUnit和NUnit
  • 原文地址:https://www.cnblogs.com/xiaohongmao/p/4115860.html
Copyright © 2011-2022 走看看