HDU 5506 - BestCoder Round #60 - GT and set

 

 

题目链接 : http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=641&pid=1003

 

 

题意 :

给N集合, 每个集合由若干个正整数组成,

要求划分为L个部分, 使得每个部分的所有集合的交集非空

能划分输出YES, 否则NO

 

思路 :

一共N个集合, 划分的个数为1 - N个, 所以当 L > N 时必然是不行的

考虑如何取到最小的划分个数cnt, 如果 cnt <= L 则可行

 

方法 : 

记录所有的数出现过的次数

每次都找一个出现次数最多的数, 将存在该数的集合作为一个划分, cnt++, 将该划分中所有集合中的数出现次数都减一, 直到不存在剩余数字为止, 再将cnt与L进行比较

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXN = 35;
const int MAX_NUM = 3e2+10;

int sett[MAXN][MAX_NUM];
int number_cnt[MAX_NUM];
int num[MAXN];
bool vis[MAXN];

int Max_Cnt()
{
    int res = 0;
    for(int i = 0; i < MAX_NUM; i++) {
        if(number_cnt[i] > number_cnt[res]) res = i;
    }
    return res;
}

void Init()
{
    memset(number_cnt, 0, sizeof(number_cnt));
    memset(vis, 0, sizeof(vis));
}

int main()
{
    int t;
    int n, l;

    scanf("%d", &t);
    while(t--) {
        Init();
        scanf("%d %d", &n, &l);
        for(int i = 0; i < n; i++) {
            scanf("%d", &num[i]);
            for(int j = 0; j < num[i]; j++) {
                scanf("%d", &sett[i][j]);
                number_cnt[sett[i][j]]++;
            }
        }
        int cnt = 0;
        for(int i = 0; i < n; i++) {
            int number = Max_Cnt();
            if(number == 0) break;
            for(int j = 0; j < n; j++) {
                if(vis[j] == 1) continue;
                for(int k = 0; k < num[j]; k++) {
                    if(sett[j][k] == number) {
                        vis[j] = 1;
                        break;
                    }
                }
                if(vis[j] == 1) {
                    for(int k = 0; k < num[j]; k++) {
                        number_cnt[sett[j][k]]--;
                    }
                }
            }
            cnt++;
        }
        if(cnt <= l) printf("YES\n");
        else printf("NO\n");
    }

    return 0;
}
View Code

 

posted @ 2015-10-19 10:12  Quinte  阅读(157)  评论(0编辑  收藏  举报