哈理工oj/hrbust 1492 盒子【最大二分匹配】

盒子
Time Limit: 1000 MSMemory Limit: 65535 K
Total Submit: 139(42 users)Total Accepted: 61(36 users)Rating: Special Judge: No
Description

     Tang长老带着集训队旅游结束后回到了实验室,还带回了好多的纪念品,实验室放满了各种物品的盒子,Tang长老说大家要注意形象,遂要求大家把盒子收拾好。实验室本来地方就比较小,所以大家想尽量腾出点地方来,还好盒子都是立方体的,一些盒子可以装在另一些盒子内部,于是大家想知道如果把一些盒子装在另一些盒子内部的话最少可以保留多少盒子露在外面,而且需要注意的是,当一个大的盒子装入一个小的盒子的时候,大的盒子的容量就会变为小的盒子的体积,即不能有超过两个盒子并列放在一个盒子内部,但是允许层层嵌套着放。

                       

 

Input

Line 1: 盒子的总数 N(2 ≤ N ≤ 500),盒子的大小关系数 M

Line 2...M+1:两个整数 A,B,表示盒子 可以放在盒子 内部。

Output

Line 1: 一个整数,表示露在外面的盒子的最少个数。

Sample Input

3 2

1 2

2 3

Sample Output
1
Author
wind

题目给出这样的全序关系:盒子 A 可以放在盒子 B 内部。相反的,盒子B是不能放在盒子A内部的,这样的一个有向图问题,第一发我竟然直接敲的并查集。。。。。。一开始的时候这个题给人的第一印象真的是并查集搞,最后查询一共有多少条路径。年轻的小伙伴就这样年轻的敲了一发并查集,然后开开心心的wa。

这个题的正确思路是这样的:

既然我们有全序关系,这里图就一定会保证不成环,如果一定不会成环的话,假如样例:

1 2

2 3

我把1放在2里边之后,2是一定不会回头有放在1里边的情况的,所以我们大可不必要担心成环问题。

既然不会成环,那我们应该如何去做这个题呢?

我们这样来想这个问题,如果1能放在2盒子里边,我们不管2能否放在其他盒子里,我们就单单讨论1和2的问题,这样我们就可以把12嵌套,变成一个盒子,这样我们就从3个盒子变成了两个盒子,我们再看2,2能放在3里边,同理就变成了一个盒子。那么我们如何实现这个问题呢、

二分匹配即可,贪心的去做,如果当前盒子能够放在其他盒子里边,我们就放在里边,当然如果盒子1可以放在盒子2,盒子2也可以放在盒子3,那么我们理应算作盒子1放在盒子3里边。

所以最终思路我们就可以相当于这样:
二分匹配匹配到一个,就相当于从n个盒子变成了n-1个盒子,如果继续向下匹配还能匹配到那么就从n-1个盒子变成了n-2个盒子。

AC代码:

#include<stdio.h>
#include<string.h>
using namespace std;
int match[505];
int vis[505];
int map[505][505];
int n,m;
int  find(int x)
{
    for(int i=1;i<=n;i++)
    {
        if(vis[i]==0&&map[x][i])
        {
            vis[i]=1;
            if(match[i]==-1||find(match[i]))
            {
                match[i]=x;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(match,-1,sizeof(match));
        memset(map,0,sizeof(map));
        while(m--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            map[x][y]=1;
        }
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof(vis));
            if(find(i))sum++;
        }
        printf("%d\n",n-sum);
    }
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值