POJ 3692 Kindergarten【最大完全子图】
题意: 给你 n 个 男的 ,m 女的,男的之间都是相互认识的,女的同样,告诉你一些男女关系,让你找出最多的人使其中任意一个人都相互认识。
分析: 同上一题。。。
/*
独立集:任意两点都不相连的顶点的集合
独立数:独立集中顶点的个数
完全子图:任意两点都相连的顶点的集合
最大完全数:最大完全子图中顶点的个数
最大完全数=原图的补图的最大独立数
最大独立数=顶点数-最大匹配数
这样,就可以求出最大完全数
完全图G就是指图G的每个顶点之间都有连边。
这样,令完全图G的阶|G|=N,那么完全图G具有如下性质:
1.图G有(N-1)*N/2条边。
2.图G上的生成树有N^(N-2)种。
3.★图G的补图G'中没有边。
由此可以引发一个很简单的定理:
★一个图T的一个完全子图G,对应它的补图T'上的一个独立集。
那么求一个图的最大完美子图就等价于它的补图的最大独立集所包含的点的个数。
于是我们可以用匹配算法解决。
*/
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<string.h> #define clr(x)memset(x,0,sizeof(x)); struct node { int to,next; }q[100000]; int tot; int head[202]; void add(int s,int u) { q[tot].to=u; q[tot].next=head[s]; head[s]=tot++; } int v[202]; int link[202]; int find(int x) { int i,k; for(i=head[x];i;i=q[i].next) { k=q[i].to; if(!v[k]) { v[k]=1; if(link[k]==0||find(link[k])) { link[k]=x; return 1; } } } return 0; } int g[202][202]; int main() { int sum,n,m,k,a,b,i,j,ca=1; while(scanf("%d%d%d",&n,&m,&k),n&&m&&k) { tot=1; clr(g); clr(head); clr(link); while(k--) { scanf("%d%d",&a,&b); g[a][b]=1; } for(i=1;i<=n;i++) for(j=1;j<=m;j++) if(!g[i][j]) add(i,j); sum=0; for(i=1;i<=n;i++) { clr(v); if(find(i)) sum++; } printf("Case %d: %d\n",ca++,n+m-sum); } return 0; }