链接:点击打开链接
题目大意:在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; }