码迷,mamicode.com
首页 > 其他好文 > 详细

uestc SOUND OF DESTINY

时间:2015-02-17 07:03:35      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:

邻接表版的DFS形式的二分匹配

增广路求最大匹配数

 

匈牙利算法的要点如下

  1. 从左边第 1 个顶点开始,挑选未匹配点进行搜索,寻找增广路。

    1. 如果经过一个未匹配点,说明寻找成功。更新路径信息,匹配边数 +1,停止搜索。
    2. 如果一直没有找到增广路,则不再从这个点开始搜索。事实上,此时搜索后会形成一棵匈牙利树。我们可以永久性地把它从图中删去,而不影响结果。
  2. 由于找到增广路之后需要沿着路径更新匹配,所以我们需要一个结构来记录路径上的点。DFS 版本通过函数调用隐式地使用一个栈,而 BFS 版本使用 prev 数组。

  详细介绍http://www.renfei.org/blog/bipartite-matching.html

bool 寻找从k出发的对应项出的可增广路
{
    while (从邻接表中列举k能关联到顶点j)
    {
        if (j不在增广路上)
        {
            把j加入增广路;
            if (j是未盖点 或者 从j的对应项出发有可增广路)
            {
                修改j的对应项为k;
                则从k的对应项出有可增广路,返回true;
            }
        }
    }
    则从k的对应项出没有可增广路,返回false;
}

void 匈牙利hungary()
{
    for i->1 to n
    {
        if (则从i的对应项出有可增广路)
            匹配数++;
    }
    输出 匹配数;
}

  

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<string>
 6 #include<queue>
 7 #include<algorithm>
 8 #include<map>
 9 #include<iomanip>
10 #include<climits>
11 #include<string.h>
12 #include<cmath>
13 #include<stdlib.h>
14 #include<vector>
15 #define INF 1e7
16 #define MAXN 100010
17 #define maxn 1000010
18 #define Mod 1000007
19 #define N 1010
20 using namespace std;
21 typedef long long LL;
22 
23 int n, m, k, a, b, ans;
24 bool vis[N];
25 int match[N];
26 vector<int> G[N];
27 
28 bool Search_path(int src)
29 {
30     for (int i = 0; i < G[src].size(); ++i) { 
31         int v = G[src][i];
32         if (!vis[v]) {              
33             vis[v] = true;            
34             if (match[v] == -1 || Search_path(match[v])) {
35                 match[v] = src;
36                 return true;
37             }
38         }
39     }
40     return false;                   
41 }
42 
43 void init()
44 {
45     ans = 0;
46     for (int i = 0; i <= n; ++i)
47         G[i].clear();
48     memset(match,-1,sizeof(match));
49 }
50 
51 int main()
52 {
53     while (cin >> n >> m) {
54         init();
55         cin >> k;
56         for (int i = 0; i < k; ++i) {
57             cin >> a >> b;
58             a--, b--;
59             G[a].push_back(b);
60         }
61         for (int i = 0; i < n; ++i) {
62             memset(vis,0,sizeof(vis));
63             if (Search_path(i))
64                 ans++;
65         }
66         cout << ans << endl;
67     }
68     return 0;
69 }

 

附上模板

技术分享
 1 // 顶点、边的编号均从 0 开始
 2 // 邻接表储存
 3 
 4 struct Edge
 5 {
 6     int from;
 7     int to;
 8     int weight;
 9 
10     Edge(int f, int t, int w):from(f), to(t), weight(w) {}
11 };
12 
13 vector<int> G[__maxNodes]; /* G[i] 存储顶点 i 出发的边的编号 */
14 vector<Edge> edges;
15 typedef vector<int>::iterator iterator_t;
16 int num_nodes;
17 int num_left;
18 int num_right;
19 int num_edges;
DS
技术分享
 1 queue<int> Q;
 2 int prev[__maxNodes];
 3 int Hungarian()
 4 {
 5     int ans = 0;
 6     memset(matching, -1, sizeof(matching));
 7     memset(check, -1, sizeof(check));
 8     for (int i=0; i<num_left; ++i) {
 9         if (matching[i] == -1) {
10             while (!Q.empty()) Q.pop();
11             Q.push(i);
12             prev[i] = -1; // 设 i 为路径起点
13             bool flag = false; // 尚未找到增广路
14             while (!Q.empty() && !flag) {
15                 int u = Q.front();
16                 for (iterator_t ix = G[u].begin(); ix != G[u].end() && !flag; ++ix) {
17                     int v = edges[*ix].to;
18                     if (check[v] != i) {
19                         check[v] = i;
20                         Q.push(matching[v]);
21                         if (matching[v] >= 0) { // 此点为匹配点
22                             prev[matching[v]] = u;
23                         } else { // 找到未匹配点,交替路变为增广路
24                             flag = true;
25                             int d=u, e=v;
26                             while (d != -1) {
27                                 int t = matching[d];
28                                 matching[d] = e;
29                                 matching[e] = d;
30                                 d = prev[d];
31                                 e = t;
32                             }
33                         }
34                     }
35                 }
36                 Q.pop();
37             }
38             if (matching[i] != -1) ++ans;
39         }
40     }
41     return ans;
42 }
BFS
技术分享
 1 int matching[__maxNodes]; /* 存储求解结果 */
 2 int check[__maxNodes];
 3 
 4 bool dfs(int u)
 5 {
 6     for (iterator_t i = G[u].begin(); i != G[u].end(); ++i) { // 对 u 的每个邻接点
 7         int v = edges[*i].to;
 8         if (!check[v]) {     // 要求不在交替路中
 9             check[v] = true; // 放入交替路
10             if (matching[v] == -1 || dfs(matching[v])) {
11                 // 如果是未盖点,说明交替路为增广路,则交换路径,并返回成功
12                 matching[v] = u;
13                 matching[u] = v;
14                 return true;
15             }
16         }
17     }
18     return false; // 不存在增广路,返回失败
19 }
20 
21 int hungarian()
22 {
23     int ans = 0;
24     memset(matching, -1, sizeof(matching));
25     for (int u=0; u < num_left; ++u) {
26         if (matching[u] == -1) {
27             memset(check, 0, sizeof(check));
28             if (dfs(u))
29                 ++ans;
30         }
31     }
32     return ans;
33 }
DFS

 

uestc SOUND OF DESTINY

标签:

原文地址:http://www.cnblogs.com/usedrosee/p/4294787.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!