【1】2018校招真题——舞会

https://www.nowcoder.com/practice/9efe02ab547d4a9995fc87a746d7eaec?tpId=90&tqId=30980&tPage=11&rp=11&ru=%2Fta%2F2018test&qru=%2Fta%2F2018test%2Fquestion-ranking

题目描述

今天,在冬木市举行了一场盛大的舞会。参加舞会的有n 位男士,从 1 到 n 编号;有 m 位女士,从 1 到 m 编号。对于每一位男士,他们心中都有各自心仪的一些女士,在这次舞会中,他们希望能与每一位自己心仪的女士跳一次舞。同样的,对于每一位女士,她们心中也有各自心仪的一些男士,她们也希望能与每一位自己心仪的男士跳一次舞。在舞会中,对于每一首舞曲,你可以选择一些男士和女士出来跳舞。但是显然的,一首舞曲中一位男士只能和一位女士跳舞,一位女士也只能和一位男士跳舞。由于舞会的时间有限,现在你想知道你最少需要准备多少首舞曲,才能使所有人的心愿都得到满足?

输入描述:

第一行包含两个整数n,m,表示男士和女士的人数。1≤n,m≤ 1000
接下来n行,
第i行表示编号为i的男士有ki个心仪的女生
然后包含ki个不同的整数分别表示他心仪的女士的编号。
接下来m行,以相同的格式描述每一位女士心仪的男士。

输出描述:

一个整数,表示最少需要准备的舞曲数目。

示例1

输入

复制

2 3
1 1
2 2 3
0
0
0

输出

复制

2

示例2

输入

复制

3 3
2 1 2
2 1 3
2 2 3
1 1
2 1 3
2 2 3

输出

复制

2

说明

对于样例2,我们只需要两首舞曲,第一首舞曲安排(1,1),(2,3),(3,2);第二首舞曲安排(1,2),(2,1),(3,3)。

解题思路:

这道题的输入略微复杂,最初我想的是,将男嘉宾心仪的女嘉宾以及女嘉宾心仪的男嘉宾合并为一个表,这个表记录男嘉宾一共需要和几个心仪的女嘉宾以及心仪自己的女嘉宾跳舞,这样有时候一支舞可以解决两个互相心仪的对象,最后记录哪位男嘉宾需要跳最多的舞,就知道一共有几首舞曲。但是这里存在一个问题,有时候多位男嘉宾都想和同一位女嘉宾跳舞,这时候男嘉宾可能要排队,需要的舞曲数量会增加,因此不合适。

这道题的解题要点有两个:

1、将男女嘉宾心仪对象合并为一个表时,可以删除重复元素(即男想和女跳,女也想和男跳),可以用set容器,保证不出现重复元素。

2、一个女生和多个男生跳舞时,跳舞的先后顺序不影响舞曲的数目。

因此当将男女嘉宾心仪对象合并为一个表后,采用遍历的方法,使用一个数组记录当前舞曲时女嘉宾是否正在跳舞,最后记录循环的次数,就可以解决。

代码如下:

//牛客网-舞会
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <set>
#include <vector>
#include <cstring>
#include <algorithm>

using namespace std;

int main(){
    //freopen("data.txt","r",stdin);
    int n, m;
    cin>>n>>m;
    int num, peo;
    set<int> s;
    set<int>::iterator it;
    vector<set<int> > fam;
    for (int i = 0; i < n; i++){
        cin>>num;
        while (num--){
            cin>>peo;
            s.insert(peo);
        }
        fam.push_back(s);
        s.clear();
    }


    for (int i = 0; i < m; i++){
        cin>>num;
        while (num--){
            cin>>peo;
            fam[peo - 1].insert(i + 1);
        }
    }


    int femal[1005];//记录当前舞曲女嘉宾是否被人约舞
    int break_point = 0;
    int ans = 0;
    while(1){
    memset (femal, 0, sizeof(femal));
    for (int i = 0; i < n; i++){
        if (fam[i].empty()) {break_point++; continue;}//表示这个男嘉宾已经不需要跳舞了
        for (it = fam[i].begin(); it != fam[i].end(); it++){
            if (femal[*it] == 0) {femal[*it]++; fam[i].erase(*it); break;}
        }
    }
    ans ++;

    if (break_point == n) {break;}//当所有男嘉宾都不需要跳舞,输出答案
    break_point = 0;
    }
    //cout << (*max_element(femal, femal + n)) << endl;
    cout<<ans-1<<endl;
    return 0;

}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值