hdu 2063(二分图最大匹配)学习笔记

解法参考:点击打开链接

数据结构书上的描述是:哈希表,又称散列表,是除顺序储存结构、链表存储结构和索引表存储结构之外的又一种存储线性表的存储结构。

我的理解是,哈希表就是一种利用一个关键字和关键字对应的储存规则进行数据储存的结构。
我们利用三个数组head[i],key[i],next[i]来描述这种关系;

具体代码如下:

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1010;
int head[maxn/2],key[maxn],next[maxn],match[maxn/2];
bool visit[maxn/2];
int num;
void Hash(int a,int b) //存储二分图;
{
    key[num]=b;
    next[num]=head[a];
    head[a]=num++;
}
bool find(int start) //遍历各个点,寻找是否有增广路径;
{
    int temp;
    for(int i=head[start];i!=-1;i=next[i])
    {
        temp=key[i];
        if(!visit[temp])
        {
            visit[temp]=true;
            if(match[temp]==-1||find(match[temp]))
            {
                match[temp]=start;
                return true;
            }
        }
    }
    return false;
}
int result(int min) //找出最大匹配的个数;
{
    int sum=0;
    for(int i=1;i<=min;i++)
    {
        memset(visit,0,sizeof(visit));
        if(find(i))
                sum++;
    }
    return sum;
}
int main()
{
    int k;
    while(scanf("%d",&k)!=EOF)
    {
        int n,m;
        scanf("%d%d",&m,&n);
        memset(head,-1,sizeof(head));
        memset(match,-1,sizeof(match));
        int min=m>n?n:m;
        int a,b;
        if(m>n)
        {
            while(k--)
            {
                scanf("%d%d",&a,&b);
                Hash(b,a);
            }
        }
        else
        {
            while(k--)
            {
                scanf("%d%d",&a,&b);
                Hash(a,b);
            }
        }
        printf("%d\n",result(min));
    }
    return 0;
}
其中,三个数组的数据分别是:
head[]                        next[]                    key[]              
head[    1    ]= 2         next[0]=-1            key[0]=1
head[    2    ]= 4         next[1]= 0            key[1]=2
head[    3    ]= 5         next[2]= 1            key[2]=3
                                  next[3]= 2            key[3]=1
                                  next[4]= 3            key[4]=3
                                  next[5]= 4            key[5]=1
可以看出,head[]中的下标是女生序号,next[]中的下标是head对应的值,key中的下标也是head对应的值,而key的取值则是男生的序号。这样,通过 for ( int  i=head[start] ; i!=-1 ; i=next[i] )这个循环,就可以按照男生和女生对应的规则进行寻找增广路的操作了。


另外,代码中主函数里,进行了比较男女人数的操作。虽然不管是男身找女生还是女生找男身,由于二分图是无向图,因此结果不会受到影响。但是,为了代码高效,尽量遍历更少的点有助于提高运算效率。所以,我们采用的是较少的人去找较多的人。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值