链接:点击打开链接
题目大意:在n个学生的配对组合中,找出没有配对的人数。也就是题目中所描述的与他人没有缘分的苦逼青年。
首先,缘分是两个人的是,题目中两人配对之后,就不与其他人再次配对。例如1,2可以配对,1,3也可以配对,但是若1,2已经配对了,那么1将无法再和3配对。也就是说,1,2,3中至少有一个人与别人有缘无分。
说白了,这题就是找二分图的最大独立集。(二分图的最大独立集=二分图节点数-二分图最大匹配数)
又是二分图,不过这个二分图和前面几个有那么点不同。将1到n个结点看做两边,形成二分图之后,会形成重复配对。比如1和2配对之后,2和1又被找作了一个配对。这样会形成最大匹配数的重复。
因此,在求出最大匹配之后,应该先将最大匹配除以二,在用节点数减去它,这样才能得到结果。
代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=500;
bool visit[maxn];
int match[maxn],head[maxn];
int key[maxn*maxn],next[maxn*maxn];
int num;
void hash(int a,int b)
{
key[num]=b;
next[num]=head[a];
head[a]=num++;
}
bool find(int start)
{
int temp;
for(int i=head[start];i!=-1;i=next[i])
{
temp=key[i];
if(!visit[temp])
{
visit[temp]=true;
if(match[temp]==-1||find(match[temp]))
{
match[temp]=start;
return true;
}
}
}
return false;
}
int result(int s)
{
int sum=0;
for(int i=0;i<s;i++)
{
memset(visit,false,sizeof(visit));
if(find(i))
sum++;
}
return sum;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(head,-1,sizeof(head));
memset(match,-1,sizeof(match));
num=0;
for(int i=0;i<n;i++)
{
int k;
scanf("%*d: (%d)",&k);
while(k--)
{
int b;
scanf("%d",&b);
hash(i,b);
}
}
printf("%d\n",n-result(n)/2);
}
return 0;
}