Codeforces Round #588 (Div. 2) C D

C - Anadi and Domino

题意

给定21张牌,每张牌的两端有两个数字,数字 1 ≤ a , b ≤ 6 1\leq a,b\leq 6 1a,b6

给定一个无向图,选择一些牌放在条边上,要求牌朝向图上的点的那一端,如果已经有牌指向这个点,那么这个点所对的所有牌的对应的一端必须是相同的数字

问最多能放多少张牌

题解

最多有7个点,21条边,21牌

我们可以把每个边指向的那个点的编号设为牌的权,枚举看看合法的情况下最多的牌有多少张

Code

int T;
int n, m;
int g[100][100];
int col[100];
bool st[100][100];
ll ans;

void dfs(int x){
    if(x == n + 1){
        memset(st, 0, sizeof(st));

        ll cnt = 0;

        for (int i = 1; i <= n; i++){
            for (int j = 1; j <= n; j++){
                if(i == j)
                    continue;
                if(!g[i][j])
                    continue;
                st[col[i]][col[j]] = 1;
                st[col[j]][col[i]] = 1;
            }
        }

        for (int i = 1; i <= 6; i++){
            for (int j = i; j <= 6; j++){
                if(st[i][j])
                    cnt++;
            }
        }

        ans = max(ans, cnt);
        return;
    }

    for (int i = 1; i <= 6; i++){
        col[x] = i;
        dfs(x + 1);
    }
}

void solve(){
    cin >> n >> m;
    for (int i = 1; i <= m; i++){
        int a, b;
        cin >> a >> b;
        g[a][b] = 1;
        g[b][a] = 1;
    }

    dfs(1);
    cout << ans << endl;
}

D - Marcin and Training Camp

题意

给定一批学生的能力值和权值,学生的能力值用2进制表示,如果人a的某一位上为1,另一个人b的这一位上为0,那么a瞧不起b,允许两人互相瞧不起

现在要组建一个人数至少2人的团队,要求里面的人不会瞧不起除他自己以外的所有人,问这个团队的最大权值是多少

题解

首先我们考虑,要让两个人互相不会瞧不起,要么就是对应位上a为0,b也为0,要不就是a上为1,b上也为1

那么就是要求得有至少两人的能力值相等才能组成一个团队

那么相同能力的人的集合就是一个初步的团队

那么其他人如果能加入到这个团队中去,必须要求这个人不会看不起这个组里的其他所有人,也就是存在一个人使得这个人看得起

等价于这个人的会的算法存在团队里的某一个人他都会,即 a ∣ b = b a|b=b ab=b,b为集合里的人

Code

#define a first
#define b second
using PII = pair<ll, ll>;

int T;
int n;
PII c[N];
bool st[N];

set<ll> s;

void solve(){
    cin >> n;
    for (int i = 1; i <= n; i++){
        cin >> c[i].a;
    }
    for (int j = 1; j <= n; j++){
        cin >> c[j].b;
    }

    sort(c + 1, c + 1 + n);

    ll ans = 0;
    for (int i = 1; i <= n; i++){
        ll cnt = 1;
        while(i < n && c[i].a == c[i + 1].a){
            cnt++;
            ans += c[i].b;
            st[i] = 1;
            s.insert(c[i].a);
            i++;
        }
        if(cnt > 1){
            ans += c[i].b;
            s.insert(c[i].a);
            st[i] = 1;
        }
    }

    for (int i = 1; i <= n; i++){
        if(!st[i]){
            for(auto j : s){
                if((c[i].a | j) == j){
                    ans += c[i].b;
                    break;
                }
            }
        }
    }
    cout << ans << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值