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] )这个循环,就可以按照男生和女生对应的规则进行寻找增广路的操作了。


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

你可能感兴趣的:(ACM)