这是做建模作业是用的的二分图匹配算法
原题如下
该代码测试数据如下
1 1
1 2
2 1
3 1
3 2
4 2
5 3
5 4
5 5
6 1
7 3
7 4
8 2
8 3
测试结果如图
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define MAXN 100
int uN = 8; //集合u顶点个数
int vN = 5; //集合u顶点个数
int edgenum = 14; //原二分图边的数目
int g[MAXN][MAXN];//存放连通关系,只存放u->v
int link[MAXN]; //存放匹配关系,linl[v] = u,只存放从右到左的匹配
int used[MAXN]; //记录当前节点是否已经遍历过,只记录v集合
/*判断节点u能不能在当前已匹配的基础上找到匹配对象v,若能,返回1,否则返回0*/
int dfs(int u);
int main()
{
/*变量,不用多管*/
int i,j;
int u,v;
int num = 0;
/*初始化存放连通关系的矩阵*/
memset(g,0,sizeof(g));
/*输入连通关系,记录*/
for(i = 0;i < edgenum;i++)
{
scanf("%d%d",&u,&v);
g[u][v] = 1;
}
/*打印,查看输入正确性*/
for(i = 1;i <= uN;i++)
{
for(j = 1;j <= vN;j++)
{
printf("%d ",g[i][j]);
}
printf("\n");
}
/*初始化匹配记录数组*/
memset(link,-1,sizeof(link));
/*匹配*/
for(u = 1;u <= uN;u++)
{
memset(used,0,sizeof(used));
if(dfs(u)) num++;
}
for(i = 1;i <= vN;i++)
{
printf("职位v%d 由选手 u%d担任\n",i,link[i]);
}
printf("num = %d\n",num);
}
/*dfs*/
int dfs(int u)
{
int v;//右边集合v
for(v = 1;v <= vN;v++)//对于u,从头去找v匹配嘛
{
if(g[u][v] && !used[v]) //找到了一个对于u来说可以匹配的
{
used[v] = 1; //标记右边节点,为 dfs(link[v])里面的递归做铺垫
/**
我个人当时对于||后面的判断迷了好一会
这么去想,倘若匹配问题变成了婚配问题
u:男方 v:女方
走到此处说明无外界干扰,u,v是可以直接匹配的,这就是link[v] == -1的情况,女方还没有男朋友
那么,问题来了,女方若是已经有了男朋友该怎么办
这就要看dfs(link[v]),翻译来说就是倘若女方v踹了当前的男朋友link[v],那么当前男朋友是否能够再找到一个漂亮女朋友
如若 dfs(link[v]) == 1,能找到,哈,那v就把link[v]给踹了,link[v]有了新的女朋友,u也有了女朋友v,皆大欢喜(匹配数目增多)
如若 dfs(link[v]) == 0,不能找到,那v表示我要长相厮守,u就没了机会,返回for循环,继续找(挖)女(墙)朋(脚)友
想要继续了解可以参考博文:https://blog.csdn.net/u013384984/article/details/90718287
*/
if(link[v] == -1 || dfs(link[v]))//倘若该节点v还没有匹配,或者(见举例)
{
link[v] = u; //将v匹配给u,退出
return 1;
}
}
}
return 0;
}