最大完全子图: 在图中找一个最大的子集,该子集中的任意两个点都相互连通。
相关概念:
独立集:任意两点都不相连的顶点的集合
独立数:独立集中顶点的个数
完全子图:任意两点都相连的顶点的集合
最大完全数:最大完全子图中顶点的个数
最大完全数=原图的补图的最大独立数
最大独立数=顶点数-最大匹配数
这样,就可以求出最大完全数。
先建立原图的补图,再求出补图的最大匹配数(用匈牙利算法),用总顶点数减去补图最大匹配数,即可得出最大完全数。(最大完全图具体有哪些顶点也可得出。把补图最大匹配的点去除,得出补图的最大独立集,这些点就在原图的最大完全子图中)
#include<bits/stdc++.h>
#define MAXN 505
using namespace std;
struct Hungary
{
struct NODE{
int f,vis;
set<int>to;
};
NODE node[MAXN];
void add(int u,int v){
node[u].to.insert(v);
}
int dfs(int x){
if(node[x].vis)return 0;
node[x].vis=1;
for(auto& j:node[x].to){
if(!node[j].f||dfs(node[j].f)){
node[j].f=x;
return 1;
}
}
return 0;
}
int hungary(int n){
int tot=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){node[j].vis=0;}
tot+=dfs(i);
}
return tot;
}
};
Hungary a;
int g,b,m;
map<int,int>mp[205];
int main()
{
//题意:b男的,g女的,男的之间都是相互认识的,女的同样,
// 告诉你m个男女关系,让你找出最多的人使其中任意两个人都相互认识.
int cntt=0;
while(cin>>g>>b>>m){
cntt++;
if(g==0&&b==0&&m==0){break;}
for(int i=1;i<=200;i++){//初始化
mp[i].clear();
a.node[i].f=a.node[i].vis=0;
a.node[i].to.clear();
}
for(int i=1;i<=m;i++){
int x,y;cin>>x>>y;
mp[x][y]=1;
}
//建立补图
for(int i=1;i<=g;i++){
for(int j=1;j<=b;j++){
if(!mp[i][j]){
a.add(i,j);
}
}
}
int tot=a.hungary(g);
//注意总人数是g+b.
printf("Case %d: %d\n",cntt,g+b-tot);
}
return 0;
}