Технокубок 2021 - Финал C. Basic Diplomacy

翻译:

Aleksey有𝑛个朋友。他现在也在度假,所以他有𝑚天来玩这款新的病毒式合作游戏!但由于它是合作的,阿列克谢将需要一个队友在每个𝑚天。

在这些日子里,每天都有一些朋友可以玩,而所有其他人都不能。每天Aleksey都必须选择一个朋友邀请他玩这个游戏(当然,他们总是同意)。然而,如果他们中的任何一个人被严格地选择超过⌈𝑚/2⌉次,那么所有其他朋友都被冒犯了。当然,阿列克谢不想冒犯任何人。

帮助他选择队友,这样没有人被严格选择超过⌈𝑚/2⌉次。

输入
每个测试包含多个测试用例。第一行包含测试用例的数量𝑡(1≤𝑡≤10000)。测试用例的描述如下。

每个测试用例的第一行包含两个整数𝑛和𝑚(1≤𝑛,𝑚≤100000),分别代表好友数和游戏天数。

下面的𝑚行中的𝑖-th包含一个整数𝑘𝑖(1≤𝑘𝑖≤𝑛),后面跟着𝑘𝑖不同的整数𝑓𝑖1,…,𝑓𝑖𝑘𝑖(1≤𝑓𝑖𝑗≤𝑛),以空格分隔-𝑖当天可用好友的索引。

保证所有测试用例中𝑛和𝑚的总和不超过100000。可以保证所有𝑘𝑖在所有测试用例的所有日子里的总和不超过200000。

输出
打印每个测试用例的答案。如果没有办法实现目标,就打印“no”。

否则,在第一行打印“YES”,在第二行打印𝑚空格分隔的整数𝑐1,…,𝑐𝑚。每个𝑐𝑖必须表示在𝑖日所选择的朋友(因此必须是𝑓𝑖𝑗中的一个)。

任何值都不能出现超过⌈𝑚2⌉次。如果有不止一个可能的答案,打印任何一个。

例子
inputCopy
2
4 - 6
1
2 1 2
3 1 2 3
4 1 2 3 4
2 2 3
1 3
2 - 2
1
1
outputCopy
是的
1 2 1 1 2 3
没有

思路:一道经典的贪心题,如果没有办法实现,那么明显就是一个朋友不得不被选择m/2次(向上取整)。所以不得不被选择,只有当天有一个人的时候存在,这样的话,这天就是固定的,我们记录上选的次数,然后之后贪心。优先选没有选过,或者被选的次数少的即可,暴力过题。

代码:

/*Looking! The blitz loop this planet to search way
 
 Only my RAILGUN can shoot it 今すぐ
 
 身体中を  光の速さで
 
 駆け巡った確かな予感
 
 掴め! 望むものなら残さず
 
 輝ける自分らしさで
 
 信じてるよ  あの日の誓いを
 
 この瞳に光る涙それさえも  強さになるから
 
 */
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
#include<stack>
using namespace::std;
typedef long long  ll;
int n,t;
inline __int128 read(){
    __int128 x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
inline void print(__int128 x){
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
}

int m,num,kl;
int bj[100005];
void wanyurukong(){
    cin>>n>>m;
    for (int i  =1; i<=n; i++) {
        bj[i]=0;
    }
    int flag=0;
    vector<int>ss[m+1];
    for (int i =1; i<=m; i++) {
        cin>>num;
        for (int j =1; j<=num; j++) {
            cin>>kl;
            ss[i].push_back(kl);
        }
        if (num==1) {
            bj[kl]++;
        }
        if (bj[kl]>(m+1)/2) {
            flag=1;
        }
    }
    if (flag) {
        printf("NO\n");return;
    }
    printf("YES\n");
    for (int i =1; i<=m; i++) {
        if (ss[i].size()==1) {
            printf("%d ",ss[i][0]);
            continue;
        }
        int xx=1e7,ls=0;
        for(int j=0 ;j<ss[i].size();j++){
            if (bj[ss[i][j]]<xx) {
                xx=bj[ss[i][j]];
                ls=ss[i][j];
            }
        }
        printf("%d ",ls);
        bj[ls]++;
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(); cout.tie();
    cin>>t;
    while (t--) {
        wanyurukong();
        //    }
        //wanyurukong
        
    }
    
}
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值