二分图匈牙利算法

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

  • 例题:

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 }

猜你喜欢

转载自www.cnblogs.com/qqq1112/p/11620774.html
今日推荐