poj 1698 二分图多重匹配
2015-08-22 20:14
393 查看
网络流解法:
容易想到将每一天看做一个点并和汇点连容量为1的边(因为一天只能做一件事情),每个电影看做一个点并和源点连容量为d的边(即几天可以完成),然后电影和对应天数连容量为1的边,求最大流判断是否满流即可。
匈牙利解法(些许改变):
容易想到将每一天看做一个点并和汇点连容量为1的边(因为一天只能做一件事情),每个电影看做一个点并和源点连容量为d的边(即几天可以完成),然后电影和对应天数连容量为1的边,求最大流判断是否满流即可。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int INF = 9999999; const int N = 400; const int M = 20000; int head ; int level ; int q ; int n, e, front, rear; void init() { e = 0; memset( head, -1, sizeof(head) ); } struct Edge { int v, next, cap; } edge[M]; void addEdge( int u, int v, int cap ) { edge[e].v = v; edge[e].cap = cap; edge[e].next = head[u]; head[u] = e++; edge[e].v = u; edge[e].cap = 0; edge[e].next = head[v]; head[v] = e++; } bool bfs( int s, int t ) { front = rear = 0; memset( level, -1, sizeof(level) ); q[rear++] = s; level[s] = 0; while ( front < rear ) { int u = q[front++]; for ( int i = head[u]; i != -1; i = edge[i].next ) { int v = edge[i].v, cap = edge[i].cap; if ( level[v] == -1 && cap > 0 ) { level[v] = level[u] + 1; q[rear++] = v; } } } return level[t] != -1; } int dfs( int u, int sum, int t ) { if ( u == t ) return sum; int os = 0; for ( int i = head[u]; i != -1; i = edge[i].next ) { int v = edge[i].v, cap = edge[i].cap; if ( level[v] == level[u] + 1 && cap > 0 ) { int tt = dfs( v, min( sum, cap ), t ); if ( tt == 0 ) continue; edge[i].cap -= tt; edge[i ^ 1].cap += tt; sum -= tt; os += tt; if ( sum == 0 ) break; } } if ( os == 0 ) level[u] = -1; return os; } int dinic( int s, int t ) { int res = 0; while ( bfs( s, t ) ) { res += dfs( s, INF, t ); } return res; } const int D = 7; int nn[D]; int main () { int _case; scanf("%d", &_case); while ( _case-- ) { scanf("%d", &n); init(); int tot = 0, wmax = -1, d, w; for ( int i = 1; i <= n; i++ ) { for ( int j = 0; j < D; j++ ) { scanf("%d", nn + j); } scanf("%d%d", &d, &w); tot += d; wmax = max( wmax, w ); addEdge( 0, i, d ); for ( int j = 0; j < D; j++ ) { if ( nn[j] == 1 ) { for ( int k = 0; k < w; k++ ) { int num = n + k * 7 + j + 1; addEdge( i, num, 1 ); } } } } int tid = n + wmax * 7 + 1; for ( int i = n + 1; i < tid; i++ ) { addEdge( i, tid, 1 ); } if ( dinic( 0, tid ) == tot ) { puts("Yes"); } else { puts("No"); } } return 0; }
匈牙利解法(些许改变):
#include <iostream> #include <cstring> #include <cstdio> #include <vector> using namespace std; const int X = 350; const int Y = 20; int head[X]; int sz[Y]; bool visit[Y]; vector<int> mark[Y]; int e; 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 ( mark[v].size() < sz[v] ) { mark[v].push_back(u); return 1; } else { for ( int j = 0; j < mark[v].size(); j++ ) { if ( dfs( mark[v][j] ) ) { mark[v][j] = u; return 1; } } } } } return 0; } const int D = 7; int nn[D]; int main () { int _case; scanf("%d", &_case); while ( _case-- ) { int n; scanf("%d", &n); init(); int tot = 0, wmax = -1, d, w; for ( int i = 0; i < n; i++ ) { for ( int j = 0; j < D; j++ ) { scanf("%d", nn + j); } scanf("%d%d", &d, &w); sz[i] = d; tot += d; wmax = max( wmax, w ); for ( int j = 0; j < D; j++ ) { if ( nn[j] == 1 ) { for ( int k = 0; k < w; k++ ) { int num = k * 7 + j; addEdge( num, i ); } } } } for ( int i = 0; i < n; i++ ) { mark[i].clear(); } int res = 0; for ( int i = 0; i < 7 * wmax; i++ ) { memset( visit, 0, sizeof(visit) ); res += dfs(i); } if ( res == tot ) { puts("Yes"); } else { puts("No"); } } return 0; }
相关文章推荐
- 位级运算的一些事
- Android-基本控件(AutoCompleteTextView,MultiAutoCompleteTextView,ToggleButton)
- 路径(path)题解
- 杭电ACM1425——sort~~水题
- 获取客户端IP
- MySQL必知必会(汇总数据, 聚集函数)
- POJ 1995 Raising Modulo Numbers【快速幂】
- 学习笔记 post和get的区别
- poj 1258 最小生成树 prim
- hdu 1017 A Mathematical Curiosity
- hdu1576 A/B
- Java Map接口LinkedHashMap
- socket编程--socket基本概念
- C#值类型与引用类型
- POJ2431 Expedition
- mysql 纸 mysql_fetch_array OR mysql_fetch_assoc OR mysql_fetch_row
- Mysql和SqlServer互相转换
- hdu1014 Uniform Generator
- Socket编程步骤
- UILabel