bzoj2044

\(dp/topsort\)求最长链 \(+\) 二分图最大匹配

每个原图中的点拆成两个,如果存在边AB,则连边\(A_i->B_j\)。跑二分图最大匹配,n-最大匹配即为答案。

struct data
{
    int a , b , c;
    bool operator<(const data x)const {return a < x.a;}
}v[N];
int f[N] , head[N] , to[N * N] , next[N * N] , cnt , vis[N] , from[N];
inline void add(int x , int y)
{
    to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
}
bool dfs(int x)
{
    int i;
    for(i = head[x] ; i ; i = next[i])
    {
        if(!vis[to[i]])
        {
            vis[to[i]] = 1;
            if(!from[to[i]] || dfs(from[to[i]]))
            {
                from[to[i]] = x;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    int n , i , j , ans1 = 0 , ans2 = 0;
    scanf("%d" , &n);
    for(i = 1 ; i <= n ; i ++ ) scanf("%d%d%d" , &v[i].a , &v[i].b , &v[i].c);
    sort(v + 1 , v + n + 1);
    for(i = 1 ; i <= n ; i ++ )
    {
        f[i] = 1;
        for(j = 1 ; j < i ; j ++ )
            if(v[j].a < v[i].a && v[j].b < v[i].b && v[j].c < v[i].c)
                f[i] = max(f[i] , f[j] + 1) , add(j , i);
        ans1 = max(ans1 , f[i]);
    }
    printf("%d\n" , ans1);
    for(i = 1 ; i <= n ; i ++ )
    {
        memset(vis , 0 , sizeof(vis));
        if(dfs(i)) ans2 ++ ;
    }
    printf("%d\n" , n - ans2);
}
posted @ 2020-10-12 21:22  INFP  阅读(48)  评论(0编辑  收藏  举报