hdu(3335)Divisibility

来源:互联网 发布:法院执行难 知乎 编辑:程序博客网 时间:2024/05/07 21:31

题目大意:给出N1000)个数字(<2^63 -1),从n中取出k个数,使得任意ab属于kab不形成整除关系。问k最大是多少

算法:有向图最小路径覆盖数

思路:因为要求取出一些点,使得他们之间没有整除关系,很容易想到利用整除关系建立一个图,然后看最多有多少个点能不相连,如果把图看作无向图,那么就很难想到做法,至少无向图最大点独立集是不能在1000的规模下运行的。如果ab的约束,我们建立一条ab的有向边,最后发现,要求的其实就是最小路径覆盖数。

最小路径覆盖数:在一个有向图中至少放几个人才能走到所有点(延边走,人可以放在任意位置,非官方解释)。

最小路径覆盖:在一个有向图中,最少用几条路径能把所有的点覆盖(路径不交叉,即每个点只属于一条路)。

当有向图无环时,可以用二分图最大匹配来求解。

最少路径覆盖= 点数 二分图最大匹配

其中二分图中的点是有原图中的点拆点后形成,一定要注意下面两点:

1 :若我们求的是路径不能交叉的最小路径覆盖,则直接二分图就行。

2 :若我们求的是路径能够交叉的最小路径覆盖,组应该先进行floyed,然后再二分图。

假设从在边(a,b(b,c), (d,b), (b,e)那么Floyed完以后相当于是又从ace另加了边来绕过原来路径中交叉的那个b点,也就是转化成了不能路径交叉的最小路径覆盖。

再回头来看我们这个题。题目要求是求最多的数,按照题目要求,在我们所建立的图里,一条路径代表的是一条约数路,也就是这一条路上我们只能最多拿出一个点,而最小路径覆盖便是所有的这样的边的个数。

 

选出n个数,任意两个数之间不能出现整除的情况,把能整除的都建边,

                要求的就是任意两个之间没有公共边的,就是最大独立集,用最小路径覆盖同样可以。

最少路径覆盖= 点数 二分图最大匹配



 #include<stdio.h>
#include<string.h>
int map[1001][1001];
int link[1001];
int mark[1001];
int m;
__int64 a[100000];
int find(int k)
{
 int i;
 for(i=1;i<=m;i++)
 {
  if(mark[i]==0&&map[k][i])
  {
   mark[i]=1;
   if(link[i]==0||find(link[i]))
   {
    link[i]=k;
    return 1;
   }
  }
 }
 return 0;
}
int main()
{
 int i,j,k,h,sum;
 
 scanf("%d",&k);
 while(k--)
 {
  scanf("%d",&m);
  memset(map,0,sizeof(map));
  memset(link,0,sizeof(link));
  for(i=1;i<=m;i++)
  {
   scanf("%I64d",&a[i]);
   for(j=1;j<i;j++)
   {
    if(a[i]%a[j]==0||a[j]%a[i]==0)
     map[j][i]=1;
   }
  }
  sum=0;
  for(i=1;i<=m;i++)
  { 
   memset(mark,0,sizeof(mark));
   if(find(i))
    sum++;
  }
  printf("%d\n",m-sum);
 }
 return 0;
}

 

 

法二:搜索:

思路:题目是要求找相互之间没有约数的最大个数
1、首先对这些数从小到大排序,定义一个数组对这些数进行纪录是否访问过
2、从小到大访问,对没访问过的进行搜索,temp++,假如mod这个数能等于0的就标记访问过了,然后对这个数搜索,直到没有数能mod这个数,则一次的搜索完被标记的这些数就不满足。
3、重复步骤2。

 

 

 #include <algorithm>  
using namespace std; 
__int64 a[1005],b[1005]; 
int t,n,i,j,k,temp; 
void BFS(int x) 

    b[x]=0; 
    for(k=x+1;k<n;k++) 
    { 
        if(a[k]%a[x]==0) 
        { 
            BFS(k); 
            break; 
        } 
    } 

int main() 

    scanf("%d",&t); 
    while(t--) 
    { 
        temp=0; 
        scanf("%d",&n); 
        for(i=0;i<n;i++) 
            scanf("%I64d",&a[i]); 
        sort(a,a+n); 
 
        for(i=0;i<n;i++) 
            b[i]=1; 
        for(i=0;i<n;i++) 
        { 
            if(b[i]==1) 
            { 
                temp++; 
                BFS(i); 
            } 
        } 
        printf("%d\n",temp); 
    } 
    return 0; 


原创粉丝点击