匈牙利算法和hopcroft_karp算法模板
2016-06-12 21:38
369 查看
今晚学习了hopcroft_karp算法,留个模板,顺便也留个匈牙利算法模板。
题目为POJ 1469,在本题中,两种算法所用时间基本一致
题目为POJ 1469,在本题中,两种算法所用时间基本一致
//hopcroft_karp算法,复杂度O(sqrt(n)*m) #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <queue> using namespace std; const int N = 320; const int INF = 0x3f3f3f3f; struct edge { int to, next; }g[N*N]; int match , head ; bool used ; int p, n; int nx, ny, cnt, dis; //nx,ny分别是左点集和右点集的点数 int dx , dy , cx , cy ; //dx,dy分别维护左点集和右点集的标号 //cx表示左点集中的点匹配的右点集中的点,cy正好相反 void add_edge(int v, int u) { g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++; } bool bfs() //寻找增广路径集,每次只寻找当前最短的增广路 { queue<int> que; dis = INF; memset(dx, -1, sizeof dx); memset(dy, -1, sizeof dy); for(int i = 1; i <= nx; i++) if(cx[i] == -1) //将未遍历的节点入队,并初始化次节点距离为0 que.push(i), dx[i] = 0; while(! que.empty()) { int v = que.front(); que.pop(); if(dx[v] > dis) break; for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(dy[u] == -1) { dy[u] = dx[v] + 1; if(cy[u] == -1) dis = dy[u]; //找到了一条增广路,dis为增广路终点的标号 else dx[cy[u]] = dy[u] + 1, que.push(cy[u]); } } } return dis != INF; } int dfs(int v) { for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(! used[u] && dy[u] == dx[v] + 1) //如果该点没有被遍历过并且距离为上一节点+1 { used[u] = true; if(cy[u] != -1 && dy[u] == dis) continue; //u已被匹配且已到所有存在的增广路终点的标号,再递归寻找也必无增广路,直接跳过 if(cy[u] == -1 || dfs(cy[u])) { cy[u] = v, cx[v] = u; return 1; } } } return 0; } int hopcroft_karp() { int res = 0; memset(cx, -1, sizeof cx); memset(cy, -1, sizeof cy); while(bfs()) { memset(used, 0, sizeof used); for(int i = 1; i <= nx; i++) if(cx[i] == -1) res += dfs(i); } return res; } int main() { int t, a, b; scanf("%d", &t); while(t--) { cnt = 0; memset(head, -1, sizeof head); scanf("%d%d", &p, &n); for(int i = 1; i <= p; i++) { scanf("%d", &a); for(int j = 0; j < a; j++) { scanf("%d", &b); add_edge(i, b); } } nx = p, ny = n; if(hopcroft_karp() == p) printf("YES\n"); else printf("NO\n"); } return 0; }
//匈牙利算法,复杂度O(nm) #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; const int N = 320; struct edge { int to, next; }g[N*N]; int match , head ; bool use ; int p, n; int nx, ny, cnt; void add_edge(int v, int u) { g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++; } bool dfs(int v) { for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(use[u] == false) { use[u] = true; if(match[u] == -1 || dfs(match[u])) { match[u] = v; return true; } } } return false; } int hungary() { int res = 0; memset(match, -1, sizeof match); for(int i = 1; i <= nx; i++) { memset(use, 0, sizeof use); if(dfs(i)) res++; } return res; } int main() { int t, a, b; scanf("%d", &t); while(t--) { cnt = 0; memset(head, -1, sizeof head); scanf("%d%d", &p, &n); for(int i = 1; i <= p; i++) { scanf("%d", &a); for(int j = 0; j < a; j++) { scanf("%d", &b); add_edge(i, b); } } nx = p, ny = n; if(hungary() == p) printf("YES\n"); else printf("NO\n"); } return 0; }
相关文章推荐
- centos fastdfs 多服务器 多硬盘 多组 配置详解
- Photoshop测量角度
- i2c协议
- linux下安装R
- Caused by: Unable to load bean: type:com.opensymphony.xwork2.ObjectFactory class:org.apache.struts2.
- 转 - ubuntu apache2下目录结构
- Linux下 swap分区 虚拟内存 的创建、调整、修改、挂载
- Linux中 LVM逻辑卷基础操作 简明教程
- 项目维护——不是有效的win32 应用程序
- OpenGL中RBO与Texture,UBO与SSBO的异同
- OpenGL中EXT,ARB扩展的关系
- linux文件管理(结构)
- 中断处理机制与工作队列
- 对linux中signal()函数的理解
- HBase 常见Shell命令总结
- ft5x0x驱动分析
- MyEclipse迁移过程中Tomcat版本不一致的解决办法
- Server Tomcat v*.* Server at localhost failed to start.
- Linux SSH生成及使用
- mplayer 音乐播放器封装类