c++世界生存手册(开始——3) 传送门,我们来了!

本文介绍了一个C++编程问题,涉及将冒险者分成两组,每组内部成员相互认识,且组间人数相近。通过将问题转化为01背包问题并使用二分图染色解决。文章提供了问题描述、输入输出格式和解题思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#本文章与前两篇相连,有兴趣的读者可以去读

故事

又过了一周,小H终于伤痕累累地带回了分组牌,但人却倒下了。原来小H为了获得分组牌与巫婆(作者自己编的怪物)战斗,却被扔了中毒药水!你拿起小H手中的分组牌,决定赶紧完成任务(时限还剩两天)不仅为了自己的小金库(其实只有2个钢板)也为了任务奖励——————完全治疗药丸。
有看了看任务单
——————————————————

  • 1,2,3报数
  • 排队接水
  • 队员分组

——————————————————
现在只剩“队员分组”了
那看看题目吧!

题目

题目描述

你的任务是把一批冒险者分成两组,使得:
每个人都被分到其中一组;
每个组都至少有一个人;
一组中的每个人都认识其他同组成员;
两组的成员人数近两接近。

这个问题可能有多个解决方案,你只要输出任意一个即可,或者输出这样的分组法不存在。
输入输出格式
输入格式:

为了简单起见,所有的人都用一个整数标记,每个人号码不同,从1到N。
输入文件的第一行包括一个整数N(2≤N≤100),N就是需要分组的总人数;接下来的N行对应了这N个人,按每个人号码的升序排列,每一行给出了一串号Aij(1≤Aij≤N,Aij≠i),代表了第i个人所认识的人的号码,号码之间用空格隔开,并以一个“0”结束。
输出格式:
如果分组方法不存在,就输出信息“No solution”(输出时无需加引号)至输出文件;否则用两行输出分组方案;第一行先输出第一组的人数,然后给出第一组成员的号码,每个号码前有一个空格,同理给出第二组的信息。请按照队员编号从小到大排序

有点没有思路,─=≡Σ(((つ•̀ω•́)つ那再看看秘籍吧!

秘籍

(⊙o⊙)…队员分组,在哪呢…?
啊哈!在这!
上面写着:这是一个存在性的01背包问题,也是一个可行性dp。可以把题想象成两个不是互相认识的话必然存在于互相排斥的两组。对这些有排斥作用的,即有联系的点放在一张图上,在新的图上跑二分图染色,就可以实现分组了。
有了思路,就简单了,开始写代码吧!

代码

#include <bits/stdc++.h>
using namespace std;
const int MN=105;
const int MM=105;
typedef long long ll;
bool g[MN][MN],f[MN][MN];
int n,num[MM][2],pre[MN][MN],ans;
vector<int> cont[MN][2];
int mtc[MN],sum=0;
void dfs(int x,int fa,int col)
{
    num[sum][mtc[x]=col]++;cont[sum][col].push_back(x);
    for (int i=1;i<=n;++i)
        if (!g[i][x] && i!=fa && x!=i)
        {
            if (mtc[i]==-1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值