华电北风吹
天津大学认知计算与应用重点实验室
日期:2015/9/13
一、二分图定义
简单来说,如果图中顶点可以分为两组,使得所有边都跨越组的边界,则这就是一个二分图。准确地说:把一个图的顶点划分为两个不相交集 U 和V ,使得每一条边都分别连接U、V中的顶点。如果存在这样的划分,则此图为一个二分图。二分图的一个等价定义是:不含有含奇数条边的环的图。
二、二分图的判断
染色法+广度优先搜索
function result=BipartiteGraph(connectGraph)
% connectGraph 联通图
[m n]=size(connectGraph);
nodelist=zeros(m,1);
nodecolor=-ones(m,1);
startNode=1;
queue=startNode;
nodelist(startNode)=1;
nodecolor(startNode)=1;
while isempty(queue)==false
i=queue(1);
queue(1)=[];
for j=1:n
if(connectGraph(i,j)>0&&i~=j)
if(nodelist(j)==0)
queue=[queue;j];
nodelist(j)=1;
nodecolor(j)=1-nodecolor(i);
else
if nodecolor(j)==nodecolor(i)
result=0;
return;
end
end
end
end
end
result=1;
三、二分图的最大匹配
匹配:在图论中,一个「匹配」(matching)是一个边的集合,其中任意两条边都没有公共顶点。例如,图 3、图 4 中红色的边就是图 2 的匹配。
最大匹配:一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。图 4 是一个最大匹配,它包含 4 条匹配边。
完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。图 4 是一个完美匹配。显然,完美匹配一定是最大匹配(完美匹配的任何一个点都已经匹配,添加一条新的匹配边一定会与已有的匹配边冲突)。但并非每个图都存在完美匹配。
#include<stdio.h>
#include<string.h>
#include <iostream>
#include <fstream>
using namespace std;
#define SIZE 10
int choice[SIZE][SIZE];
int visited[SIZE], link[SIZE];
int M, N;
int find(int pos)
{
int i;
for (i = 1; i <= N; i++)
{
if (visited[i] == 0 && choice[pos][i] == 1)
{
visited[i] = 1;
if (link[i] == 0 || find(link[i]))
{
link[i] = pos;
return 1;
}
}
}
return 0;
}
int main()
{
ifstream in(".\\input.txt");
cin.rdbuf(in.rdbuf());
int K, i, a, b, ans;
while (cin>>K && K)
{
memset(choice, 0, sizeof(choice));
memset(link, 0, sizeof(link));
cin >> M >> N;
while (K--)
{
cin >> a >> b;
choice[a][b] = 1;
}
ans = 0;
for (i = 1; i <= M; i++)
{
memset(visited, 0, sizeof(visited));
if (find(i))
ans++;
}
cout << ans << endl;
}
system("pause");
return 0;
}