C. Basic Diplomacy 思维
题目大意:
你有 \(n\) 个朋友,你休息 \(m\) 天,每天都有一部分朋友有空,你每天可以选择一个朋友来陪你,但是如果有一个朋友陪你的天数大于 \(m/2\) 向上取整,那么就会让别人神奇。
希望你帮他做出一种选择,没有一个人陪他的天数大于 \(m/2\) 向上取整,如果可以,输出 \(YES\) 和每一天陪他的人,如果不行,输出 \(NO\)
题解:
- 首先因为是只要不大于 \(m/2\) 的向上取整
- 那么其实只要只有1个人有空的天数小于等于 \(m/2\) (同一个人)就是 YES
- 然后按照每一天的人数的 size 从小到大即可
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
int p[maxn],vis[maxn],ans[maxn];
vector<int>a[maxn];
void init(int n){
for(int i=0;i<=n;i++) p[i] = i,a[i].clear(),vis[i] = 0;
}
bool cmp(int i,int j){
return a[i].size()<a[j].size()?true:false;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);init(max(n,m));
for(int i=1,x,y;i<=m;i++){
scanf("%d",&x);
while(x--){
scanf("%d",&y);
a[i].push_back(y);
}
}
sort(p+1,p+1+m,cmp);
for(int i=1;i<=m;i++){
// printf("p[%d]=%d\n",i,p[i]);
int u = p[i],pos = 0;
for(int j=1;j<a[u].size();j++){
if(vis[a[u][j]]<vis[a[u][pos]]) pos = j;
}
// printf("i = %d u = %d %d\n",i,u,a[u][pos]);
ans[u] = a[u][pos];
vis[a[u][pos]]++;
}
int len = (m+1)/2,flag = 1;
for(int i=1;i<=n;i++) if(vis[i]>len) flag = 0;
if(!flag) printf("NO\n");
else{
printf("YES\n");
for(int i=1;i<=m;i++) printf("%d ",ans[i]);
printf("\n");
}
}
}
/*
100
5 6
3 1 2 3
2 1 2
1 1
1 1
1 1
2 1 2
*/