题目描述
Aleksey has nn friends. He is also on a vacation right now, so he has mm days to play this new viral cooperative game! But since it's cooperative, Aleksey will need one teammate in each of these mm days.
On each of these days some friends will be available for playing, and all others will not. On each day Aleksey must choose one of his available friends to offer him playing the game (and they, of course, always agree). However, if any of them happens to be chosen strictly more than \left\lceil\dfrac{m}{2}\right\rceil⌈2m⌉ times, then all other friends are offended. Of course, Aleksey doesn't want to offend anyone.
Help him to choose teammates so that nobody is chosen strictly more than \left\lceil\dfrac{m}{2}\right\rceil⌈2m⌉ times.
输入格式
Each test contains multiple test cases. The first line contains the number of test cases tt ( 1 \le t \le 10\,0001≤t≤10000 ). Description of the test cases follows.
The first line of each test case contains two integers nn and mm ( 1\leq n, m\leq 100\,0001≤n,m≤100000 ) standing for the number of friends and the number of days to play, respectively.
The ii -th of the following mm lines contains an integer k_iki ( 1\leq k_i\leq n1≤ki≤n ), followed by k_iki distinct integers f_{i1}fi1 , ..., f_{ik_i}fiki ( 1\leq f_{ij}\leq n1≤fij≤n ), separated by spaces — indices of available friends on the day ii .
It is guaranteed that the sums of nn and mm over all test cases do not exceed 100\,000100000 . It's guaranteed that the sum of all k_iki over all days of all test cases doesn't exceed 200\,000200000 .
输出格式
Print an answer for each test case. If there is no way to achieve the goal, print "NO".
Otherwise, in the first line print "YES", and in the second line print mm space separated integers c_1c1 , ..., c_mcm . Each c_ici must denote the chosen friend on day ii (and therefore must be one of f_{ij}fij ).
No value must occur more than \left\lceil\dfrac{m}{2}\right\rceil⌈2m⌉ times. If there is more than one possible answer, print any of them.
最容易想到的贪心是,对于m个组,依次遍历,找到其中最玩的天数最少的来增加一天,如果最少的也不能加,那么输出-1
显然这种方法是不可取的,一旦我们最后一天只有一个可选,而这个恰恰被选满了,这样就
比如下面这样
1 2 3 4 5
1 2 3
1 2
12
1
所以我们还有再加上一次贪心,那就是先进行总天数少的,比如上图案例,我们从下到上,总体一次贪心,内部一次贪心,那么问题就得到了解决
# include<iostream>
# include<complex.h>
# include<string.h>
# include<cstring>
# include<vector>
# include<algorithm>
# include<iomanip>
using namespace std;
typedef complex<double>cp;
# define mod 9999991
typedef long long int ll;
typedef struct
{
vector<int>v;
int id;
} xinxi;
xinxi s[100000+10];
bool cmp(xinxi a,xinxi b)
{
return a.v.size()<b.v.size();
}
int sum[1000000+10];
int ans[1000000+10];
int len;
int main ()
{
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
int up=m/2;
len=0;
for(int i=1; i<=n; i++)
{
sum[i]=0;
}
if(m%2)
up++;
for(int i=1; i<=m; i++)
{
int k;
cin>>k;
s[i].id=i;
s[i].v.clear();
while(k--)
{
int x;
cin>>x;
s[i].v.push_back(x);
}
}
sort(s+1,s+1+m,cmp);
int flag=0;
for(int i=1; i<=m; i++)
{
int minn=9999999;
int id;
for(auto it:s[i].v)
{
if(sum[it]<minn)
{
id=it;
minn=sum[it];
}
}
if(minn<up)
{
sum[id]++;
ans[s[i].id]=id;
len++;
}
else
{
flag=1;
break;
}
}
if(flag==0)
{
cout<<"YES"<<'\n';
for(int i=1; i<=m; i++)
{
cout<<ans[i]<<" ";
}
cout<<'\n';
}
else
{
cout<<"NO"<<'\n';
}
}
return 0;
}