hdu 3081 Marriage Match II isap+二分+并查集
2015-05-28 20:47
357 查看
题意:n个女孩,n个男孩。每轮女孩各自找一个男孩配对,要求是:这个男孩之前没和她配对过,这个男孩没和她吵架过,这个男孩没和她的朋友吵架过(程序猿的写照233333...)。给出男女孩从未超过架的关系,和女孩间朋友的关系,问这种配对游戏最多能进行多少轮。
很难想到要用网络流来做这道题。首先女孩之间的关系很明显可以用并查集处理,接下来处理女孩与男孩间的关系。注意到游戏如果能进行k轮,那么每个女孩就要找k个满足上述条件的男孩,这时候我们就可以用最大流的流量限制来处理女孩选男孩的关系。即女孩对所有满足条件男孩连一条流量为1的边,表示能配对一次,同时建超源超汇,超源向每个女孩连一条k大小的边,表示最多进行k轮,同理男孩则向超汇连一条k大小的边。最后跑一发最大流,以此作为能不能进行进行k轮的标准。
详见代码。
很难想到要用网络流来做这道题。首先女孩之间的关系很明显可以用并查集处理,接下来处理女孩与男孩间的关系。注意到游戏如果能进行k轮,那么每个女孩就要找k个满足上述条件的男孩,这时候我们就可以用最大流的流量限制来处理女孩选男孩的关系。即女孩对所有满足条件男孩连一条流量为1的边,表示能配对一次,同时建超源超汇,超源向每个女孩连一条k大小的边,表示最多进行k轮,同理男孩则向超汇连一条k大小的边。最后跑一发最大流,以此作为能不能进行进行k轮的标准。
详见代码。
#include <map> #include <set> #include <queue> #include <stack> #include <vector> #include <string> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 #define ls rt << 1 #define rs rt << 1 | 1 #define pi acos(-1.0) #define eps 1e-8 #define asd puts("sdfsdfsdfsdfsdfsdf"); typedef long long ll; typedef pair<ll, int> pl; const int inf = 0x3f3f3f3f; const int N = 250; const int st = 0, ed = 205, nv = 206; struct node{ int v, w, nxt; }e[N*N]; struct pp{ int x, y; }p[N*N]; int head[N<<1]; int cur[N<<1]; int dep[N<<1]; int gap[N<<1]; int s[N<<1], top; queue <int> q; int fa[N<<1]; bool vis ; int n, m, f; int cnt; void init() { for( int i = 1; i <= n; ++i ) fa[i] = i; } void add( int u, int v, int w ) { //printf("%d %d %d\n", u, v, w); e[cnt].w = w; e[cnt].v = v; e[cnt].nxt = head[u]; head[u] = cnt++; e[cnt].w = 0; e[cnt].v = u; e[cnt].nxt = head[v]; head[v] = cnt++; } int dfs( int x ) { while( x != fa[x] ) x = fa[x]; fa[x] = x; return fa[x]; } void ff( int x, int y ) { x = dfs( x ); y = dfs( y ); if( x != y ) fa[y] = x; } void rebuild( int w ) { cnt = 0; memset( head, -1, sizeof( head ) ); for( int i = 1; i <= n; ++i ) { add( st, i, w ); add( i+n, ed, w ); } for( int i = 1; i <= n; ++i ) for( int j = 1; j <= n; ++j ) vis[i][j] = 0; for( int i = 1; i <= m; ++i ) { int x = p[i].x, y = p[i].y; for( int j = 1; j <= n; ++j ) { if( fa[j] == fa[x] ) { if( !vis[j][y] ) { add( j, y+n, 1 ); vis[j][y] = 1; } } } } } void rev_bfs( ) { memset( gap, 0, sizeof( gap ) ); memset( dep, -1, sizeof( dep ) ); while( !q.empty() ) q.pop(); q.push( ed ); dep[ed] = 0; gap[0] = 1; while( !q.empty() ) { int u = q.front(); q.pop(); for( int i = head[u]; ~i; i = e[i].nxt ) { int v = e[i].v; if( ~dep[v] ) continue; dep[v] = dep[u] + 1; gap[dep[v]]++; q.push( v ); } } } int isap() { memcpy( cur, head, sizeof cur ); rev_bfs(); int flow = 0, i, u = st; top = 0; while( dep[st] < nv ) { if( u == ed ) { int tmp, minn = inf; for( i = 0; i < top; ++i ) { if( minn > e[s[i]].w ) { minn = e[s[i]].w; tmp = i; } } for( i = 0; i < top; ++i ) { e[s[i]].w -= minn; e[s[i]^1].w += minn; } flow += minn; top = tmp; u = e[s[top]^1].v; } for( i = cur[u]; ~i; i = e[i].nxt ) { if( e[i].w > 0 && dep[u] == dep[e[i].v] + 1 ) { cur[u] = i; break; } } if( ~i ) { s[top++] = cur[u]; u = e[i].v; } else { if( 0 == (--gap[dep[u]]) ) break; int minn = nv; for( i = head[u]; ~i; i = e[i].nxt ) { int v = e[i].v; if( e[i].w > 0 && minn > dep[v] ) { minn = dep[v]; cur[u] = i; } } dep[u] = minn + 1; gap[dep[u]]++; if( u != st ) { u = e[ s[--top]^1 ].v; } } } return flow; } int main() { int tot; for( scanf("%d", &tot); tot--; ) { scanf("%d%d%d", &n, &m, &f); init(); for( int i = 1; i <= m; ++i ) { scanf("%d%d", &p[i].x, &p[i].y); } int u, v; for( int i = 1; i <= f; ++i ) { scanf("%d%d", &u, &v); ff( u, v ); } for( int i = 1; i <= n; ++i ) fa[i] = dfs(i); int l = 0, r = n, mid, ans = 0; while( l <= r ) { mid = ( l + r ) >> 1; rebuild( mid ); //最多进行mid轮匹配 int tmp = isap(); //printf("%d %d\n", mid, tmp); if( mid * n <= tmp ){ ans = mid; l = mid + 1; } else if( mid * n > tmp ) r = mid - 1; } printf("%d\n", ans); } return 0; }
相关文章推荐
- 电话本
- DiscuzX2.5数据库字典 值得学习
- weblogic 获取路径问题
- 微信运营:必须收藏的101条万能微信标题公式
- ART
- LAMP网站性能优化
- 筛法求素数
- android开发中关于VersionCode和VersionName
- scala目录
- 随笔
- 全屏加载loading显示的解决方法
- sql知识随笔(二)
- C++语言基础 例程 应用系统开发:银行储蓄系统
- scala命令
- UVA 10934 Dropping water balloons(经典DP)
- Ubuntu下开发编译运行C程序
- Android编程常见问题
- 疯狂Java学习笔记(54)----------详解Java IO(全面)
- Scrapy安装、爬虫入门教程、爬虫实例(豆瓣电影爬虫)
- fzu2153 A simple geometric problems