bzoj 2044 三维导弹拦截——DAG最小路径覆盖(二分图)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2044
还以为是CDQ。发现自己不会三维以上的……
第一问可以n^2。然后是求最长不下降子序列吗?dilworth好像不能用吧。
那就是能从自己转移到哪些状态就从自己向哪些状态连边,然后就是最小路径覆盖了。用二分图的 n-最大匹配 。
注意:没有位置的限制所以可以先按 x 排序!
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1005,M=N*N; int n,hd[N<<1],xnt,to[M],nxt[M],dp[N],ans,per[N]; bool vis[N]; struct Node{ int x,y,z; bool operator< (const Node &b) const {return x<b.x;} }a[N]; struct Ed{ int x,y;Ed(int x=0,int y=0):x(x),y(y) {} }ed[M]; void add(int x,int y) { to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt; } bool dfs(int cr) { for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]) { vis[v]=1; if(!per[v]||dfs(per[v])) { per[v]=cr;return true; } } return false; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); sort(a+1,a+n+1); for(int i=1;i<=n;i++) { dp[i]=1; for(int j=1;j<i;j++) if(a[j].x<a[i].x&&a[j].y<a[i].y&&a[j].z<a[i].z) dp[i]=max(dp[i],dp[j]+1),ed[++xnt]=Ed(j,i); ans=max(ans,dp[i]); } printf("%d\n",ans); ans=0; int tmp=xnt; xnt=0; for(int i=1;i<=tmp;i++) add(ed[i].x,ed[i].y); for(int i=1;i<=n;i++) { memset(vis,0,sizeof vis); ans+=dfs(i); } printf("%d\n",n-ans); return 0; }