1. 程式人生 > >bzoj 2044 三維導彈攔截——DAG最小路徑覆蓋(二分圖)

bzoj 2044 三維導彈攔截——DAG最小路徑覆蓋(二分圖)

geo () cstring space 路徑 href ++ void 自己

題目: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; }

bzoj 2044 三維導彈攔截——DAG最小路徑覆蓋(二分圖)