数学建模-匈牙利算法-二分图匹配-C语言

这是做建模作业是用的的二分图匹配算法
原题如下
在这里插入图片描述
该代码测试数据如下

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;
}


  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值