图论-二分图匹配-匈牙利算法

有关概念:

  二分图:图G中的点集可以分为两个互不相交的子集,且G中的每条边连接的两个点分别属于这两个子集

  二分图匹配:二分图G的子图M中每个结点上只连一条边,则称M为一个匹配

  极大匹配:无法再向二分图中加边且满足匹配条件的匹配

  最大匹配:所有极大匹配中边数最多的一个

  增广路:若P为图G上连接两个未匹配结点的路径,且已匹配边和未匹配边在P上交替出现,则称P为相对于M的一条增广路

  匈牙利算法即用来求二分图的极大匹配

思路:

  在图G中找出增广路P,对P上每一条边取反(即已匹配边改为未匹配边,未匹配边改为已匹配边),重复直到找不到增广路为止

样例推导:

给出一幅二分图

从X1开始,搜到X1-Y1,成增广路,连接X1-Y1

[ATTENTION]从X2开始,搜到X2-Y1-X1-Y3,成增广路

图论-二分图匹配-匈牙利算法 - xqmmcqs - xqmmcqs的博客

[ATTENTION] 取消连接X1-Y1,连接X1-Y3,X2-Y1

图论-二分图匹配-匈牙利算法 - xqmmcqs - xqmmcqs的博客

从X3开始,搜到X3-Y1-X2,不通,不作更改

图论-二分图匹配-匈牙利算法 - xqmmcqs - xqmmcqs的博客

搜到X3-Y2,成增广路,连接X3-Y2

图论-二分图匹配-匈牙利算法 - xqmmcqs - xqmmcqs的博客

从X4开始,搜到X4-Y3-X1-Y1-X2,不通,不作更改

图论-二分图匹配-匈牙利算法 - xqmmcqs - xqmmcqs的博客

搜到X4-Y4,成增广路,连接X4-Y4

图论-二分图匹配-匈牙利算法 - xqmmcqs - xqmmcqs的博客

至此找出极大增广路

邻接表

 1 #include<cstdio>
 2 #include<cstring>
 3 #define MAXN 
 4 int n,m,cnt,match[MAXN],head[MAXN],ans;
 5 bool check[MAXN];
 6 struct node
 7 {
 8     int v,next;
 9 }edge[MAXN*5];
10 void add(int x,int y)
11 {
12     edge[++cnt].next=head[x];
13     head[x]=cnt;
14     edge[cnt].v=y;
15 }
16 bool Hungary(int u)
17 {
18     for(int i=head[u];i;i=edge[i].next)
19     {
20         int v=edge[i].v;
21         if(!check[v])//判断v是否在增广路中
22         {
23             check[v]=true;
24             if(!match[v]||Hungary(match[v]))
25             {
26                 match[v]=u;//v对应u
27                 return true;
28             }
29         }
30     }
31     return false;
32 }
33 int main()
34 {
35     //省略输入 
36     for(int i=1;i<=n;i++)
37     {
38         if(!match[i])
39         {
40             memset(check,false,sizeof(check));
41             if(Hungary(i))ans++;
42         }
43     }
44     printf("%d\n",ans);
45     return 0;
46 }

邻接矩阵

 1 #include<cstdio>
 2 #include<cstring>
 3 #define MAXN 
 4 int n,m,cnt,match[MAXN],map[MAXN][MAXN],ans;
 5 bool check[MAXN];
 6 bool Hungary(int u)
 7 {
 8     for(int i=1;i<=n;i++)
 9     {
10         if(!check[i]&&map[u][i])
11         {
12             check[i]=true;
13             if(!match[i]||Hungary(match[i]))
14             {
15                 match[i]=u;
16                 return true;
17             }
18         }
19     }
20     return false;
21 }
22 int main()
23 {
24     //省略输入 
25     for(int i=1;i<=n;i++)
26     {
27         if(!match[i])
28         {
29             memset(check,false,sizeof(check));
30             if(Hungary(i))ans++;
31         }
32     }
33     printf("%d\n",ans);
34     return 0;
35 }

*参考:https://www.byvoid.com/blog/hungary/

http://baike.baidu.com/view/501081.htm

http://baike.baidu.com/link?url=QbNL6DpNwvt1u3Yka7I-xy9Ymig1HNZid4j2MGsDxlyzCOXcdhjkG8sSJvBtK2zkZzOU007ooiSiujjwOpYCMq

http://baike.baidu.com/link?url=YStVW2tIYiH6flGjr0VqIu44uM9Vhckq8pyKLpt651sGYpOFHsGI3TL9d2T5Tmy84QXmt__mVc0zerNUBfeecK

posted @ 2016-10-16 00:02  xqmmcqs  阅读(409)  评论(0编辑  收藏  举报