二分图匈牙利算法

匿名 (未验证) 提交于 2019-12-03 00:13:02

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

  • 例题:

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 }

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!