HDU3335 Divisibility Dilworth定理+最小路徑覆蓋
阿新 • • 發佈:2017-10-13
dag圖 系統 targe eof pre ret stream sin long
首先需要一些概念: 有向圖,最小路徑覆蓋,最大獨立集,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\n",cnt-ans);
}
return 0;
}
HDU3335 Divisibility Dilworth定理+最小路徑覆蓋