二分图模型中的最大独立集问题:在二分图G=(X,Y;E)中求取最小的顶点集V* ⊂ {X,Y},使得边 V*任意两点之间没有边相连。
公式: 最大独立集顶点个数 = 总的顶点数(|X|+|Y|)- 最大匹配数
题意:幼儿园有G个小女孩和B个小男孩,小女孩彼此之间互相认识,小男孩彼此之间互相认识。一些小女孩与一些小男孩之间也互相认识。现在老师要选一些小朋友做一个游戏,这些小朋友之间必须互相认识。问老师最多可以选多少个小朋友。
解题:满足X集合,Y集合,E边集合的题目可以用二分图模型来解。此题中的E={(i,j)| i与j相互不认识}。所有图初始为1,输入边则改为0。这样求最大匹配。
关于为什么要这样构图:X(Y)中都是相互认识的,也就是有关系的(有边相连)。但是二分图中X(Y)中的点之间是没有关系,是独立的点。所以建边的时候要反过来。
看看别人的博客怎么说: http://www.2cto.com/kf/201401/273879.html
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std; const int N=,INF=0x3f3f3f3f;
int bmap[N][N],cx[N],cy[N],dx[N],dy[N];
bool bmask[N];
int nx,ny,dis,ans;
bool searchpath()
{
queue<int> q;
dis=INF;
memset(dx,-,sizeof(dx));
memset(dy,-,sizeof(dy));
for(int i=;i<=nx;i++)
{
if(cx[i]==-){ q.push(i); dx[i]=; }
while(!q.empty())
{
int u=q.front(); q.pop();
if(dx[u]>dis) break;
for(int v=;v<=ny;v++)
{
if(bmap[u][v]&&dy[v]==-)
{
dy[v]= dx[u] + ;
if(cy[v]==-) dis=dy[v];
else
{
dx[cy[v]]= dy[v]+;
q.push(cy[v]);
}
}
}
}
}
return dis!=INF;
}
int findpath(int u)
{
for(int v=;v<=ny;v++)
{
if(!bmask[v]&&bmap[u][v]&&dy[v]==dx[u]+)
{
bmask[v]=;
if(cy[v]!=-&&dy[v]==dis) continue;
if(cy[v]==-||findpath(cy[v]))
{
cy[v]=u; cx[u]=v;
return ;
}
}
}
return ;
}
void maxmatch()
{
ans=;
memset(cx,-,sizeof(cx));
memset(cy,-,sizeof(cy));
while(searchpath())
{
memset(bmask,,sizeof(bmask));
for(int i=;i<=nx;i++)
if(cx[i]==-) ans+=findpath(i);
}
}
int main()
{
//freopen("test.txt","r",stdin);
int m,i,j,k=,cas;
while(scanf("%d%d%d",&nx,&ny,&m)!=EOF)
{
if(!nx) break;
for(i=;i<=nx;i++)
for(j=;j<=ny;j++)
bmap[i][j]=;
while(m--)
{
scanf("%d%d",&i,&j);
bmap[i][j]=;
}
maxmatch();
printf("Case %d: ",k++);
printf("%d\n",nx+ny-ans);
}
return ;
}