HDU3335 Divisibility Dilworth定理+最小路径覆盖

首先需要一些概念: 有向图,最小路径覆盖,最大独立集,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;
}
原文地址:https://www.cnblogs.com/hua-dong/p/7661709.html