Algorithm.( Augmenting Path Algorithm )

Input:
    An X-Y bigraph G, a matching M in G,
    and the set U of M-unsaturated vertices in X.
        
Idea:
    Explore M-alternating paths form U,
    letting S ⊆ X and T ⊆ Y be the sets of vertices reached.
    Marks vertices of S that have been explored for path extensions.
    As a vertex is reached, record the vertex from which it is reached.
        
Initialization:
    S = U and T = ∅

Iteration:
    If S has no unmarked vertex,
    stop and report T ∪ ( X - S ) as a minimun cover and M as a maximum matching.
    Otherwise, select an unmarked x ∈ S, consider each y ∈ N( x ) such that xy ∉ M,
    if y is unsaturated, terminate and report an M-augmenting path from U to y.
    Otherwise, y is matched to some w ∈ X by M.
    In this case, include y in T ( reached from x ) and include w in S ( reached from y ).
    After exploring all such edges incident to x, mark x and iterate.


#include <iostream>
#include <cstring>
using namespace std;#define NODE_SIZE 100bool bigraph[NODE_SIZE][NODE_SIZE];
int parent[NODE_SIZE];
bool visit[NODE_SIZE];int num = 0;
int nodes1, nodes2, edges;bool find_augmenting_path( int start_node ){for( int end_node = 1; end_node <= nodes2; ++end_node ){if( bigraph[start_node][end_node] && visit[end_node] == false ){visit[end_node] = true;if( parent[end_node] == 0 ||find_augmenting_path( parent[end_node] ) ){parent[end_node] = start_node;return true;}}}return false;
}int main(){memset( bigraph, false, sizeof( bigraph ) );memset( visit, false, sizeof( visit ) );memset( parent, 0, sizeof( parent ) );cin >> nodes1 >> nodes2 >> edges;for( int i = 1; i <= edges; ++i ){int start_node, end_node;cin >> start_node >> end_node;bigraph[start_node][end_node] = true;}for( int node = 1; node <= nodes1; ++node ){memset( visit, false, sizeof( visit ) );if( find_augmenting_path( node ) )num++;}cout << num << endl;return 0;
}

简单应用:

在 raw * col 的棋盘上,有些格子不能放。用1 * 2 的方块铺棋盘。问能不能铺满?

比方:

思路:

对每种格子着色,黑白相间,不能放的格子除。

然后白色的格子为一个部集,黑色的格子也为一个部集。两个部集进行最大匹配,

若最后匹配数目等于黑色或者白色格子的总数,即为可行;否则,不可行。

法1:

// 1143MS
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;#define CHESSBOARD_SIZE 50
#define GRAPH_SIZE 1100bool chessboard[CHESSBOARD_SIZE][CHESSBOARD_SIZE];
bool bigraph[GRAPH_SIZE][GRAPH_SIZE];
bool visit[GRAPH_SIZE];
int parent[GRAPH_SIZE];
int raws, cols, holes;bool find_augmenting_path( int source ){for( int target = 1; target <= raws * cols; ++target ){if( bigraph[source][target] && !visit[target] ){visit[target] = true;if( parent[target] == 0 || find_augmenting_path( parent[target] ) ){parent[target] = source;return true;}}}return false;
}int maximum_matching(){int ans = 0;for( int i = 1; i <= raws * cols; ++i ){memset( visit, false, sizeof( visit ) );if( find_augmenting_path( i ) )ans++;}return ans;
}int main(){memset( chessboard, false, sizeof( chessboard ) );memset( bigraph, false, sizeof( bigraph ) );memset( visit, true, sizeof( visit ) );memset( parent, 0, sizeof( parent ) );cin >> raws >> cols >> holes;int num = raws * cols;for( int i = 1; i <= holes; ++i ){int raw, col;cin >> col >> raw;chessboard[raw][col] = true;num--;}for( int raw = 1; raw <= raws; ++raw ){for( int col = 1; col <= cols; ++col ){if( chessboard[raw][col] )continue;int p1 = cols * ( raw - 1 ) + col;if( raw > 1 && chessboard[raw - 1][col] == false ){int p2 = p1 - cols;bigraph[p1][p2] = true;}if( raw < raws && chessboard[raw + 1][col]== false ){int p2 = p1 + cols;bigraph[p1][p2] = true;}if( col > 1 && chessboard[raw][col - 1] == false ){int p2 = p1 - 1;bigraph[p1][p2] = true;}if( col < cols && chessboard[raw][col + 1] == false ){int p2 = p1 + 1;bigraph[p1][p2] = true;}}}int ans = maximum_matching();if( ans == num )cout << "YES" << endl;elsecout << "NO" << endl;return 0;
}

法2:

// 725k 32MS
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;#define NODE_SIZE 50struct Position{Position(){raw = -1;col = -1;};Position( int r, int c ){raw = r;col = c;};int raw;int col;
};enum State { INIT, HOLE, BLACK, WHITE };
State chessboard[NODE_SIZE][NODE_SIZE];Position parent[NODE_SIZE * NODE_SIZE];
bool visit[NODE_SIZE * NODE_SIZE];
int raws, cols, holes;int direction[5][3] = {{ 0, 0, 0 },{ 0, 1, 0 },{ 0, 0, 1 },{ 0, -1, 0 },{ 0, 0, -1 }
};bool find_augmenting_path( Position source ){for( int i = 1; i <= 4; ++i ){int dx = direction[i][1];int dy = direction[i][2];int next_raw = source.raw + dx;int next_col = source.col + dy;if( next_raw >= 1 &&next_raw <= raws &&next_col >= 1 &&next_col <= cols ){int one_dim_pos = cols * ( next_raw - 1 ) + next_col;if( chessboard[next_raw][next_col] == WHITE && !visit[one_dim_pos] ){visit[one_dim_pos] = true;if( ( parent[one_dim_pos].raw == -1 &&parent[one_dim_pos].col == -1 ) ||find_augmenting_path( parent[one_dim_pos] ) ){parent[one_dim_pos].raw = source.raw;parent[one_dim_pos].col = source.col;return true;}}}}return false;
}int main(){cin >> raws >> cols >> holes;vector< Position > black_rects;vector< Position > white_rects;for( int raw = 1; raw <= raws; ++raw ){for( int col = 1; col <= cols; ++col ){chessboard[raw][col] = INIT;}}memset( visit, false, sizeof( visit ) );int rects = raws * cols - holes;for( int i = 1; i <= holes; ++i ){int col, raw;cin >> col >> raw;chessboard[raw][col] = HOLE;}for( int raw = 1; raw <= raws; ++raw ){for( int col = 1; col <= cols; ++col ){if( chessboard[raw][col] == HOLE )continue;if( ( col % 2 && raw % 2 ) ||( ( raw % 2 == 0 ) && ( col % 2 == 0 ) ) ){chessboard[raw][col] = BLACK;black_rects.push_back( Position( raw, col ) );}else{chessboard[raw][col] = WHITE;white_rects.push_back( Position( raw, col ) );}}}const int black_rects_num = black_rects.size();const int white_rects_num = white_rects.size();if( black_rects_num == 0 ||rects % 2 != 0 ||black_rects_num != white_rects_num ){cout << "NO" << endl;}else{int ans = 0;for( int i = 0; i < black_rects_num; ++i ){memset( visit, false, sizeof( visit ) );if( find_augmenting_path( black_rects[i] ) )ans++;}if( ans == black_rects_num ){cout << "YES" << endl;}else{cout << "NO" << endl;}}return 0;
}

POJ 3692

建反图,求最大独立集

#include <iostream>
#include <cstring>
using namespace std;#define MAX_SIZE 210bool bigraph[MAX_SIZE][MAX_SIZE];
bool visits[MAX_SIZE];
int parents[MAX_SIZE];
int B, G, M;bool find_augmenting_path( int source ){for( int target = 1; target <= B; ++target ){if( bigraph[source][target] && !visits[target] ){visits[target] = true;if( parents[target] == 0 || find_augmenting_path( parents[target] ) ){parents[target] = source;return true;}}}return false;
}int maximum_matching(){int ans = 0;for( int source = 1; source <= G; ++source ){memset( visits, false, sizeof( visits ) );if( find_augmenting_path( source ) )ans++;}return ans;
}int main(){int nCase = 1;while( true ){memset( bigraph, true, sizeof( bigraph ) );memset( parents, 0, sizeof( parents ) );memset( visits, false, sizeof( visits ) );cin >> G >> B >> M;if( G == 0 && B == 0 && M == 0 )break;for( int i = 1; i <= M; ++i ){int u, v;cin >> u >> v;bigraph[u][v] = false;}int max_matching = maximum_matching();int ans = G + B - max_matching;cout << "Case " << nCase << ": " << ans << endl;nCase++;}return 0;
}

二分图最大匹配 -- 匈牙利算法相关推荐

  1. 二分图最大匹配—匈牙利算法

    二分图:又叫二部图,图G中顶点集V可以分成互不相交的子集(X,Y),并且图中的每一条边所关联的点分别属于两个不同的顶点集,则图G叫二分图.(不含奇环) 二分图的匹配:给定一个二分图G的子图M,M的边集 ...

  2. 二分图最大匹配-匈牙利算法

    今天介绍 匈牙利算法 : 匈牙利算法,是基于Hall定理中充分性证明的思想,它是部图匹配最常见的算法,该算法的核心就是寻找增广路径,由匈牙利数学家Edmonds于1965年提出,因而得名. 先介绍一下 ...

  3. 二分图最大匹配 - 匈牙利算法

    问题描述: X集合(编号1~m),Y集合(编号m+1~n).n,m<100. 给出若干组合(x, y)(相当于映射x->y),问最都能同时有几个组合(分配). 分析: 题目可能简化描述得不 ...

  4. 二分图最大匹配——匈牙利算法

    二分图最大匹配 (一).二分图的介绍 1.定义 2.充要条件 (二).二分图的匹配 1.二分图的最大匹配 2.增广路径 3.匈牙利算法 (1).复杂度 (2).算法思路 (3).代码实现 (一).二分 ...

  5. 二分图最大匹配(匈牙利算法Dinic算法)

    二分图最大匹配: 给出一个二分图,左边有若干个节点,右边有若干个节点,左边的节点想到匹配右边的节点,每个左边的节点每个都有若干个可以选择的对象,每个左边节点只能选择一个右边节点,每个右边节点也只能被选 ...

  6. 二分图最大匹配(匈牙利算法) POJ 3020 Antenna Placement

    题目传送门 1 /* 2 题意:*的点占据后能顺带占据四个方向的一个*,问最少要占据多少个 3 匈牙利算法:按坐标奇偶性把*分为两个集合,那么除了匹配的其中一方是顺带占据外,其他都要占据 4 */ 5 ...

  7. NYOJ 题目239 月老的难题 (二分图最大匹配-匈牙利算法模板)

    月老的难题 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 月老准备给n个女孩与n个男孩牵红线,成就一对对美好的姻缘. 现在,由于一些原因,部分男孩与女孩可能结成幸福的一 ...

  8. NYOJ - 239 - 月老的难题 ( 二分图最大匹配 匈牙利算法 )

    描述 月老准备给n个女孩与n个男孩牵红线,成就一对对美好的姻缘. 现在,由于一些原因,部分男孩与女孩可能结成幸福的一家,部分可能不会结成幸福的家庭. 现在已知哪些男孩与哪些女孩如果结婚的话,可以结成幸 ...

  9. [HDOJ2819]Swap(二分图最大匹配, 匈牙利算法)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=2819 题意:给一张n*n的01矩阵,可以任意交换其中的行或者列,问是否可以交换出来一个对角 ...

最新文章

  1. sed 每次只替换一行
  2. 解决SQL Server里sp_helptext输出格式错行问题
  3. POJ1125 Floyd
  4. openwrt转载--openwrt框架分析
  5. 在51CTO安了家。。。。
  6. 算法设计与分析(第三周)递归/迭代求Fibonacci前n项 【以及递归算法速度慢的原因】
  7. Lnmp环境安装禅道项目管理软件
  8. js javascript 判断字符串是否包含某字符串,String对象中查找子字符,indexOf
  9. python工资这么高为什么不学-为什么Python岗位薪资越来越高
  10. 【大数据编程笔记】大数据背景,案例,概念
  11. CISCO ASA防火墙配置实验
  12. 基于Cocos2d-x开发guardCarrot--8 《保卫萝卜2》关卡选择场景开发
  13. “进度条”博客——第十三周
  14. python,错误、调试和测试
  15. mobx中跟新了数据视图没变化_如何做一个好的大数据平台架构
  16. Jmeter 面试题
  17. Excel-单纯形法(大M法)求解 直接求解与规划求解功能
  18. 慕课翁凯习题集答案01厘米转换为英尺,英寸问题
  19. 关于计算机取代学校的英语作文,关于网络教室将取代传统的教室英语作文
  20. php对接京东宙斯平台,利用京东联盟API获取自定义推广链接

热门文章

  1. laravel多种安装方法
  2. 五个项目管理学习笔记.沟通技巧II
  3. Java并发编程 LockSupport源码分析
  4. 在网上找了一些j2ee的视频教程,有需要的朋友可以看看
  5. 【Linux 内核】编译 Linux 内核 ⑤ ( 查看 .config 编译配置文件 | 正式编译内核 )
  6. 【Groovy】MOP 元对象协议与元编程 ( 使用 Groovy 元编程进行函数拦截 | 重写 MetaClass#invokeMethod 方法拦截 JDK 中已经定义的函数 )
  7. 【Android 逆向】frida 框架安装 ( 设置 Python 3.7 版本 | 安装 frida 12.7.5 版本 | 安装 frida-tools 5.1.0 版本 )
  8. 【Flutter】Flutter 启动白屏问题 ( 问题描述 | 在 launch_background.xml 中设置启动过渡 UI )
  9. 【C 语言】文件操作 ( 文件结尾判定 )
  10. 【集合论】序关系 ( 偏序集元素之间的关系 | 可比 | 严格小于 | 覆盖 | 哈斯图 )