首先需要一些概念: 有向图,最小路径覆盖,最大独立集,Dilworth,偏序集,跳舞链(DLX)....
理解一:
对于DAG图,有:最大独立集=点-二分匹配数,二分匹配数=最小路径覆盖。
而无向图,定点N>20差不多就是NP问题。
所以此题的除的关系设成单向,然后求匹配数。
理解二:
没看懂QwQ,不过最小拦截系统中庸到了这个思想。
理解三:
跳舞链,就是线性代数的方式解决?
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<memory.h>
using namespace std;
const int maxn=1010;
int used[maxn],link[maxn],map[maxn][maxn];
long long a[maxn],b[maxn];
int n,m,cnt;
bool _find(int v){
for(int i=1;i<=cnt;i++)
if(!used[i]&&map[v][i]){
used[i]=1;
if(!link[i]||_find(link[i])){
link[i]=v;
return true;
}
}
return false;
}
int main()
{
int i,j,T,ans;
scanf("%d",&T);
while(T--){
memset(map,0,sizeof(map));
memset(link,0,sizeof(link));
ans=cnt=0;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%lld",&a[i]);
sort(a+1,a+n+1);
if(n>=1) b[++cnt]=a[1];
for(i=2;i<=n;i++) if(a[i]!=a[i-1]) b[++cnt]=a[i];
for(i=1;i<=cnt;i++)
for(j=i+1;j<=cnt;j++)
if(b[j]%b[i]==0) map[i][j]=1;
for(i=1;i<=cnt;i++){
memset(used,0,sizeof(used));
if(_find(i)) ans++;
}
printf("%d
",cnt-ans);
}
return 0;
}