hdu1054 匈牙利算法(增广路) (附匈牙利算法模板)

来源:互联网 发布:软件三层结构 编辑:程序博客网 时间:2024/05/18 18:55

嗯。。。。今天开始写博客。。。。大一过去一半了。。。希望下半年能有个好的开始吧

先贴上百度百科里面对匈牙利算法的描述

算法轮廓:
⑴置M(这里M是图的一个子边集, 也就是现在要求的最大匹配的边集)为空
⑵找出一条增广路径P,通过异或操作获得更大的匹配M’代替M
⑶重复⑵操作直到找不出增广路径为止

而在代码的实现中,我们考虑枚举二分图左边点集中的点x的所有出边指向的点y,若y之前没有被匹配,那么(x,y)就是一对可以的匹配,我们便

将匹配数+1,。否则,我们便考虑给算法中已经于y匹配的点x'另找一个匹配,如果这时我们给x'找到了另外的匹配,那么(x,y)便可以成为一对行

的匹配。给x'寻找匹配的过程我们可以用dfs解决。从而我们有了解决最大匹配的方法。

下面给出我的模板

vector<int> v[]; //储存边的邻接表int pre[]; // pre[i]记录与i匹配的左边点集中的点bool flag[]; //记录是否访问过某一个点bool find(int x) {    int len = v[x].size();    rep(i, 0, len) {        if(!flag[v[x][i]]) {            flag[v[x][i]] = true;            if(pre[v[x][i]] == -1 || find(pre[v[x][i]])) {                pre[v[x][i]] = x;                return true;            }        }    }    return false;}int hungary(int n) {    int ans = 0;    memset(pre, 255, sizeof(pre));    rep(i, 0, n) {        memset(flag, 0, sizeof(flag));        if(find(i)) ans++;    }    return ans;//ans即为所求的最大匹配}


然后以hdu的1054作为例题

题目传送门http://acm.hdu.edu.cn/showproblem.php?pid=1054

(另一道poj上的二分匹配,不过加了二分枚举答案一步,链接点这儿)

完全就是简单的匹配,不过建的是无向图而已

由于模板是在这道题做出之后才有的。。。所以模板的形式和题目AC的代码略有不同。。。

#include <iostream>#include <cstdio>#include <vector>using namespace std;#define MAX_N 1505int pre[MAX_N];bool flag[MAX_N];vector<int> map[MAX_N];int n;int find(int cur){int k;vector<int>::iterator iter, end = map[cur].end();for (iter = map[cur].begin(); iter < end; iter++){k = *iter;if (!flag[k]){flag[k] = true;if (pre[k] == -1 || find(pre[k])){pre[k] = cur;return 1;}}}return 0;}int main(){int i, j, r, k, num, sum;while (scanf("%d", &n) != EOF){memset(pre, -1, sizeof(pre));for (i = 0; i < n; i++) map[i].clear();for (i = 0; i < n; i++){scanf("%d:(%d)", &k, &num);for (j = 0; j < num; j++){scanf("%d", &r);map[k].push_back(r);map[r].push_back(k);}}sum = 0;for (i = 0; i < n; i++){memset(flag, false, sizeof(flag));sum += find(i);}printf("%d\n", sum / 2);}return 0;}



当然这个问题里面还涉及到了最小点覆盖和最大匹配的关系,明显图中所有的点都可以在最大匹配的边集中找到包含这个点的边,所以只要从每个边上

各选一个点的话,这时这些点肯定满足覆盖。而如果减少一个点的话,这些点就相当于从一个不完全匹配的边集中找到的点,这时肯定有边集没有涉及

到的点,所以可以保证这时的答案是最小的符合条件的。而至于答案中是sum/2,是因为无向图的话,这个算法对同一条边会求两次,所以会除以2

0 0
原创粉丝点击