poj 2289 二分+多重匹配
2015-08-23 12:24
447 查看
最大值最小的一个常用方法是二分。二分“the size of the largest group”然后每次判断最大匹配数是否为人数即可。
#include <iostream> #include <cstring> #include <cstdio> #include <cctype> using namespace std; const int X = 1000; const int Y = 500; int head[X]; int cnt[Y]; int mark[Y][X]; bool visit[Y]; int n, m, e, sz; void init() { e = 0; memset( head, -1, sizeof(head) ); } struct Edge { int v, next; } edge[X * Y]; void addEdge( int u, int v ) { edge[e].v = v; edge[e].next = head[u]; head[u] = e++; } int dfs( int u ) { for ( int i = head[u]; i != -1; i = edge[i].next ) { int v = edge[i].v; if ( !visit[v] ) { visit[v] = 1; if ( cnt[v] < sz ) { mark[v][cnt[v]++] = u; return 1; } else { for ( int j = 0; j < cnt[v]; j++ ) { if ( dfs( mark[v][j] ) ) { mark[v][j] = u; return 1; } } } } } return 0; } bool hungary() { memset( cnt, 0, sizeof(cnt) ); for ( int i = 0; i < n; i++ ) { memset( visit, 0, sizeof(visit) ); if ( !dfs(i) ) return false; } return true; } const int L = 501; char list[L]; int main () { while ( scanf("%d%d", &n, &m) != EOF ) { if ( n == 0 && m == 0 ) break; init(); getchar(); for ( int i = 0; i < n; i++ ) { gets(list); int len = strlen(list); int j = 0, ret; while ( 1 ) { while ( !isdigit(list[j]) ) j++; ret = 0; while ( isdigit(list[j]) ) { ret = ret * 10 + list[j] - '0'; j++; } addEdge( i, ret ); if ( j == len ) break; } } int lb = 1, ub = n; while ( lb < ub ) { sz = ( lb + ub ) >> 1; if ( hungary() ) { ub = sz; } else { lb = sz + 1; } } printf("%d\n", lb); } return 0; }
相关文章推荐
- Android 中像素px和dp的转化
- Linux下搭建python + nodejs + express环境
- 软件测试之-测试覆盖率
- poj1273(最大流)
- 版本适配的问题(持续更新)
- 如何使用 RMAN 异构恢复一些表空间
- LeetCode "Paint House II"
- asp.net mvc @Html.Raw 作用
- HDU 1879 最小生成树
- 小意境,大智慧
- fzu 2105(区间更新+位拆分)
- 【C语言经典实例】-switch分支结构-模拟自动售货机
- SQL操作表数据_update操作
- 笔记本惠普CQ14-a003TX加装内存和SSD固态硬盘
- elk分析nginx访问日志
- LVS----三种director的方式
- 王爽《汇编语言》第2版-----3、寄存器(内存访问)
- Android 开源组件PagerBottomTabStrip 快速构建底部导航栏
- SVN服务器搭建和使用(一)
- squid的安装与配置