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
" , ans1);
    for(i = 1 ; i <= n ; i ++ )
    {
        memset(vis , 0 , sizeof(vis));
        if(dfs(i)) ans2 ++ ;
    }
    printf("%d
" , n - ans2);
}
原文地址:https://www.cnblogs.com/shikeyu/p/13805613.html