1. 程式人生 > >HDU3335 Divisibility Dilworth定理+最小路徑覆蓋

HDU3335 Divisibility Dilworth定理+最小路徑覆蓋

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定理+最小路徑覆蓋