|
偏序集的两个定理: 定理1) 令(X,≤)是一个有限偏序集,并令r是其最大链的大小。则X可以被划分成r个但不能再少的反链。 其对偶定理称为Dilworth定理: 定理2) 令(X,≤)是一个有限偏序集,并令m是反链的最大的大小。则X可以被划分成m个但不能再少的链。 即:链的最少划分数=反链的最长长度 相关的题目有pku 1065,pku 3636,pku 1548 POJ 3636:
#include<iostream> #include<algorithm> #define M 20002 using namespace std; struct Node{ int h,w; }a[M]; int tail[M],n; void LIS(int n){ int i,j,m,len,mid,low,high; len=1;tail[1]=a[1].h; for(i=2;i<=n;i++){ if(tail[len]<=a[i].h) { len++; tail[len]=a[i].h; } else{ low=1;high=len; while(low<high){ mid=(low+high)/2; if(a[i].h>=tail[mid]) low=mid+1; else high=mid; } tail[low]=a[i].h; } } printf("%d\n",len); } bool cmp(Node a,Node b){ if(a.w!=b.w)return a.w>b.w; else return a.h<b.h; } int main() { int i,j,k,cas; scanf("%d",&cas); while(cas--){ scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d%d",&a[i].w,&a[i].h); sort(a+1,a+1+n,cmp); LIS(n); } //system("pause"); return 0; }
POJ 1548:
#include<iostream> #include<algorithm> using namespace std; int k,a[700],tail[800],b[860]; void LIS(){ int i,j,m,n,len,mid,left,right; n=1; for(i=k-1;i>=1;i--) b[n++]=a[i]; n--; len=1;tail[1]=b[1]; for(i=2;i<=n;++i){ if(b[i]>tail[len]){ len++; tail[len]=b[i]; } else{ left=1;right=len; while(left<right){ //二分查找插入的位置 mid=(left+right)/2; if(tail[mid]<b[i]) left=mid+1; else right=mid; } tail[left]=b[i]; //插入 } } printf("%d\n",len); } int main() { int i,j,m,n; while(1){ k=1; scanf("%d%d",&i,&j); if(i==-1&&j==-1) break; a[k++]=j; while(scanf("%d%d",&i,&j)){ if(i==0&&j==0 ){ LIS(); break; } a[k++]=j; } } }
|