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;
}

 

posted on 2018-08-25 17:49  Narh  阅读(195)  评论(0编辑  收藏  举报

导航