题目大意:
A有n个朋友,m天假期,每天有一些朋友有空,他每天可以找一个人玩,但是每个朋友不能被选择超过
⌈
m
/
2
⌉
⌈m/2⌉
⌈m/2⌉次,不然其他朋友会觉得被冷落QAQ~
问:
能不能找到这样一个方案,如果能,print YES并给出方案,不能则print NO。
题解:
仔细想想,其实会发现,只有当某些天只有同一个人有空,而且天数超过
⌈
m
/
2
⌉
⌈m/2⌉
⌈m/2⌉才会没有解,其余情况均有解~
比如
6 2
1 1
1 1
1 1
1 1
1 2
1 2
这种情况没有解~但是下面这种情况就有解
6 2
1 1
1 1
1 1
2 1 2
1 2
1 2
存储结构体的时候,可以按天存,也可以按朋友存。制定方案时,先选有空时候多的朋友,当一个朋友被选择了 ⌈ m / 2 ⌉ ⌈m/2⌉ ⌈m/2⌉次后,就换人,如下面的样例~
7 3
1 3
2 1 2
2 1 2
2 1 2
2 1 2
2 1 2
2 1 2
代码如下:
#include <bits/stdc++.h>
using namespace std;
struct node{
int cnt;
int index;
vector<int> avail;
node(){cnt = 0;}
};
bool cmp(node p, node q){
return p.cnt>q.cnt;
}
int sel[100005], num[100005];
node friends[100005];
int main(){
int t;
cin >> t;
while (t --) {
int n, m, ans = 0;
cin >> n >> m;
memset(friends, 0, sizeof(friends));
memset(sel, 0, sizeof(sel));
memset(num, 0, sizeof(num));
for(int i = 1; i <= m; i ++){
int k;
cin >> k;
for(int j = 0; j < k; j++){
int a;
cin >> a;
if(k == 1) {
sel[i] = a;
num[a] ++;
ans ++;
}
friends[a].index = a;
friends[a].cnt++;
friends[a].avail.push_back(i);
}
}
sort(friends+1, friends+n+1, cmp);
int c = ceil(m/2.0), flag = 1;
for(int i = 1; i <= n; i ++){
if(num[i] > c) flag = 0;
}
if(flag == 0) printf("NO\n");
else{
int flag2 = 1;
for(int i = 1; i <= n; i ++){
//对于每个朋友,安排他们,天数不超过c
for(int j = 0; j < friends[i].cnt; j ++){
if(num[friends[i].index] < c && ans < m){
if(sel[friends[i].avail[j]] == 0){
sel[friends[i].avail[j]] = friends[i].index;
num[friends[i].index] ++;
ans ++;
}
}
else break;
}
if(ans == m) break;
}
printf("YES\n");
for(int i = 1; i <= m; i ++){
if(i == m) printf("%d\n", sel[i]);
else printf("%d ", sel[i]);
}
}
}
return 0;
}