#本文章与前两篇相连,有兴趣的读者可以去读
故事
又过了一周,小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