二分图匈牙利算法

Posted qqq1112

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分图匈牙利算法相关的知识,希望对你有一定的参考价值。

   求二分图的算法——匈牙利

  • 例题:

https://www.luogu.org/problem/P3386

  • 思路:

首先二分图是一个求一堆东西(例如狗),喜欢一些东西(例如肉),但是他们喜欢的肉不同,求最大限度能满足多少条狗的问题。那么我们可以画一个图,把狗放在一侧,把肉放在一侧。 如果第i只狗, 喜欢第j个肉,那么,就从i-->j连一条有向边。 然后, 我们用贪心的思想进行dfs。 我们定义choose[i]表示第i个肉被第choose[i]个狗获得。 然后我们定义一个vis数组,防止死循环。 我们枚举1 ~ n,dfs判断第i只狗能否吃到肉。 dfs中,我们枚举i所喜欢的肉,如果第j个肉没有被吃 || 吃这个肉的狗可以吃别的肉,那么就return 1(及当前狗可以吃到肉),否则return 0。 如果return 1,就ans++(及可以吃到自己喜欢的肉的狗的数量++)。 注意:每次dfs都要把vis清空。 最后答案就是ans。 

  • 代码:
 1 #include <bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 using namespace std;
 4 int n, m, edge, head[100001], vis[100001], choose[100001], num, ans;
 5 struct node
 6 
 7     int next, to;
 8 stu[10000001];
 9 inline void add(int x, int y)//存图 
10 
11     stu[++num].next = head[x];
12     stu[num].to = y;
13     head[x] = num;
14     return;
15 
16 inline int dfs(int u)//贪心dfs 
17 
18     for(register int i = head[u]; i; i = stu[i].next)//枚举当前点所喜欢的东西 
19     
20         int k = stu[i].to;
21         if(vis[k])
22         
23             continue;
24         
25         vis[k] = 1;
26         if(!choose[k] || dfs(choose[k]))//如果没人要或者要这个东西的人可以要别的东西 
27         
28             choose[k] = u;//这个东西的物主变成u了 
29             return 1;
30         
31     
32     return 0;
33 
34 signed main()
35 
36     scanf("%d %d %d", &n, &m, &edge);
37     for(register int i = 1, x, y; i <= edge; ++i)
38     
39         scanf("%d %d", &x, &y);
40         if(x > n || y > m)//特判一下 
41         
42             continue;
43         
44         add(x, y);//建边 
45     
46     for(register int i = 1; i <= n; ++i)
47     
48         memset(vis, 0, sizeof(vis));//清空 
49         ans += dfs(i);//直接+就好了 
50     
51     printf("%d", ans);
52     return 0;
53 

 

以上是关于二分图匈牙利算法的主要内容,如果未能解决你的问题,请参考以下文章

匈牙利算法解决二分图匹配

二分图匹配(匈牙利算法模板)

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

二分图 匈牙利算法

匈牙利算法dfs模板 [二分图][二分图最大匹配]

匈牙利 算法&模板