一开始做题,我就以为是单纯的最大匹配,还觉得案例是不是有错,后来才知道这是一个叫什么“最大独立集”的东东,因为第一次接触,于是到处百度,到后来发现概念还是很模糊。。囧。。。。下面先通俗的解释一下“最大独立集”,(很形象生动。。有助理解,不要看了文字就烦就不想看)相信会对第一次接触“最大独立集”的人有帮助
一如往常,个人觉得在看一个知识概念之前,先粗略的了解一下这是个什么东东,然后再去看概念会比较好,结合题目来看,题目求的是“romantically involved”(后面解释为“浪漫组合”).每个人都有自己想与之一起学习的人,有的有多个,有的有0个,那么会有多少个这样的“浪漫组合”,我最开始的解决就是用0~N个人去和0~N个人匹配,那么得到的结果除以2就是结果(因为如果0想和7一起,匹配一次,那么7也会和0匹配一次,但是总共只有N个人,就相当于只组合成了一对“浪漫组合”),后面发现输出的答案都和案例输出不同....其实,原因是这样的,在其中的一些人组成“浪漫组合"之后,剩下的那些人就只能自己和自己”浪漫“啦.....比如案例中的7个人组合了2对,我们就可以看做他们组成两个独立的集合(两个”浪漫组合“),也就是剩下三个人互相不能组成,就各自单独为一个独立的集合(也就是”浪漫组合“),那么总共就有5个“浪漫组合”、也就是5个独立集。。。。相信到这里大概知道最大独立集这个看似深奥的东东的本质了吧
那么现在根据公式 最大独立集=顶点数-最大匹配 (这个结合刚刚的分析不可能不懂)说白了就是很裸的匈牙利模板算法,直接给出代码
/*
注意理解最大独立集
*///2484MS 4152K
#include<stdio.h>
#include<string.h>
#define MAX 1001
int N;
int map[MAX][MAX];
int link[MAX];
bool useif[MAX];
void init()
{
int st,m,to;
memset(map,0,sizeof(map));
for(int i=0;i<N;i++)
{
scanf("%d: (%d)",&st,&m);
while(m--)
{
scanf("%d",&to);
map[st][to]=1;
}
}
}
bool can(int t)
{
for(int i=0;i<N;i++)
{
if(!useif[i] && map[t][i])
{
useif[i]=true;
if(link[i]==-1 || can(link[i]))
{
link[i]=t;return true;
}
}
}
return false;
}
int match()
{
int sum=0;
memset(link,-1,sizeof(link));
for(int i=0;i<N;i++)
{
memset(useif,false,sizeof(useif));
if(can(i))
sum++;
}
return sum;
}
int main()
{
while(~scanf("%d",&N))
{
init();
printf("%d\n",N-(match()+1)/2);//注意这里....匹配的时候返回的次数多了一半
}
return 0;
}