这两道题目都是多重二分匹配+枚举的做法,或者可以用网络流,实际上二分匹配也就实质是网络流,通过枚举区间,然后建立相应的图,判断该区间是否符合要求,并进一步缩小范围,直到求出解。不同之处在对是否满足条件的判断,可以求最大流或者最大匹配看匹配数目是否满足题意。

POJ 2289:

多重二分匹配:360ms

 #include <iostream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define esp 1e-6
#define pb push_back
#define in freopen("in.txt", "r", stdin);
#define out freopen("out.txt", "w", stdout);
#define print(a) printf("%d\n",(a));
#define bug puts("********))))))");
#define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
#define inf 0x0f0f0f0f
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef vector<int>:: iterator IT;
#define N 1111
#define M 555
int n, m;
bool use[M];
int link[M][N], cap[M];
VI g[N];
bool dfs(int x)
{
int t;
for(int i = ; i < (int)g[x].size(); i++)
if(!use[t = g[x][i]])
{
use[t] = true;
if(link[t][] < cap[t])
return link[t][++link[t][]] = x, true;
else
{
for(int j = ; j <= cap[t]; j++)
{
// use[t] = true;
if(dfs(link[t][j]))
return link[t][j] = x, true;
}
}
}
return false;
}
bool match(void)
{
memset(link, , sizeof(link));
for(int i = ; i <= n; i++)
{
memset(use, , sizeof(use));
if(!dfs(i))
return false;
}
return true;
}
void update(int mid)
{
for(int i = ; i <= m; i++)
cap[i] = mid;
}
int main(void)
{
while(scanf("%d%d", &n, &m), n)
{
// for(int i = 1; i )
char ch;
for(int i = ; i <= n; i++)
{
g[i].clear();
scanf("%*s%c", &ch);
while(ch != '\n')
{
int k;
scanf("%d%c", &k, &ch);
g[i].pb(k+);
}
}
int l = , r = n, mid;
int ans = n;
while(l <= r)
{
mid = (l+r)>> ;
update(mid);
if(match())
{
ans = min(mid, ans);
r = mid-;
}
else l = mid+;
}
printf("%d\n", ans);
}
return ;
}

网络流:589ms

 #include <iostream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define esp 1e-6
#define pb push_back
#define in freopen("in.txt", "r", stdin);
#define out freopen("out.txt", "w", stdout);
#define print(a) printf("%d\n",(a));
#define bug puts("********))))))");
#define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
#define inf 0x0f0f0f0f
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef vector<int>:: iterator IT;
#define N 5000
#define M 600000
struct EDGE
{
int i, c;
EDGE *next, *ani;
} *Edge[N], E[M << ], BE[M << ], *tag[N];
int Dfn[N], Now[N], cnt;
int n, m, src, sink, ndot; void init(void)
{
cnt = ;
memset(Edge, , sizeof(Edge));
src = , sink = ;
ndot = *n+*m+;
}
void add(int i, int j, int c, EDGE &e1, EDGE &e2)
{
e1.i = j, e1.c = c, e1.next = Edge[i], e1.ani = &e2, Edge[i] = &e1;
e2.i = i, e2.c = , e2.next = Edge[j], e2.ani = &e1, Edge[j] = &e2;
BE[cnt] = E[cnt], BE[cnt + ] = E[cnt + ];
cnt += ;
}
int ISAP(int s, int end, int flow)
{
if(s == end)
return flow;
int i, now = , vary, tab = ndot - ;
for(EDGE *p = Edge[s]; p && flow; p = p->next)
if(p->c)
{
// bug
if(Dfn[s] == Dfn[i = p->i] + )
vary = ISAP(i, end, min(p->c, flow)),
p->c -= vary, p->ani->c += vary, now += vary, flow -= vary;
if(p->c)
tab = min(tab, Dfn[i]);
if(Dfn[src] == ndot)
return now;
}
if(now == )
{
if(--Now[Dfn[s]] == )
Dfn[src] = ndot;
Now[Dfn[s] = tab +]++;
}
// print(now);
return now;
}
int max_flow(int s, int end)
{
memset(Dfn, , sizeof(Dfn));
memset(Now, , sizeof(Now));
Now[] = ndot;
int ret = ;
for(; Dfn[s] < ndot;)
{
ret += ISAP(s, end, inf);
}
return ret;
}
void Restore(void)
{
for(int i = ; i < cnt; i++)
E[i] = BE[i];
}
void update(int c)
{
Restore();
for(int i = n+; i <= n+m; i++)
{
tag[*i]->c = c;
}
}
int main(void)
{
while(scanf("%d%d", &n, &m), n)
{ char ch;
init();
for(int i = ; i <= n; i++)
{
scanf("%*s%c", &ch);
while(ch != '\n')
{
int k;
scanf("%d%c", &k, &ch);
k += n+;
add(*i^, *k, , E[cnt], E[cnt + ]);
}
add(*i, *i^, , E[cnt], E[cnt + ]);
add(src, *i, , E[cnt], E[cnt + ]);
}
for(int i = ; i <= m; i++)
{
add(*(i+n), *(i+n)^, inf, E[cnt], E[cnt + ]);
tag[*(i+n)] = &E[cnt];
add(*(i+n)^, sink, inf, E[cnt], E[cnt + ]);
}
int l = , r = n, mid;
int ans = n;
while(l <= r)
{
mid = (l+r)>> ;
update(mid);
if(max_flow(src, sink) == n)
{
// bug
ans = min(mid, ans);
r = mid-;
}
else l = mid+;
}
printf("%d\n", ans);
}
return ;
}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

POJ 3189:

多重二分匹配:32ms

 #include <iostream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define esp 1e-6
#define pb push_back
#define in freopen("in.txt", "r", stdin);
#define out freopen("out.txt", "w", stdout);
#define print(a) printf("%d\n",(a));
#define bug puts("********))))))");
#define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef vector<int>:: iterator IT;
#define N 30
#define M 1111
int n, m, mx, mi;
bool use[N];
int link[N][M], cap[N], rank1[M][N];
bool dfs(int x)
{
for(int i = ; i <= m; i++)
if(rank1[x][i] >= mi && rank1[x][i] <= mx && !use[i])
{
use[i] = true;
if(link[i][] < cap[i])
return link[i][++link[i][]] = x, true;
else
for(int j = ; j <= cap[i]; j++)
{
if(dfs(link[i][j]))
return link[i][j] = x, true;
}
}
return false;
}
bool match(void)
{
memset(link, , sizeof(link));
for(int i = ; i <= n; i++)
{
memset(use, , sizeof(use));
if(!dfs(i))
return false;
}
return true;
}
int main(void)
{
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++)
for(int j = ; j <= m; j++)
{
int x;
scanf("%d", &x);
rank1[i][x] = j;
}
for(int i = ; i <= m; i++)
scanf("%d", cap + i);
int ans = m;
mx = mi = ;
while(mi <= mx && mx <= m)
{
if(match())
{
ans = min(mx-mi+, ans);
mi++;
}
else mx++;
}
printf("%d\n", ans);
return ;
}

网络流:110ms

 #include <iostream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define esp 1e-6
#define pb push_back
#define in freopen("in.txt", "r", stdin);
#define out freopen("out.txt", "w", stdout);
#define print(a) printf("%d\n",(a));
#define bug puts("********))))))");
#define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef vector<int>:: iterator IT;
#define N 3000
#define M 50000 struct EDGE
{
int i, c;
EDGE *next, *ani;
} *Edge[N], E[M << ], BE[M << ];
int n, m, mx, mi, src, sink, cnt, ndot;
int cap[N], rank1[M][N], vis[N], dfn[N], Now[N]; void add(int i, int j, int c, EDGE &e1, EDGE &e2)
{
e1.i = j, e1.c = c, e1.next = Edge[i], e1.ani = &e2, Edge[i] = &e1;
e2.i = i, e2.c = , e2.next = Edge[j], e2.ani = &e1, Edge[j] = &e2;
BE[cnt] = E[cnt], BE[cnt + ] = E[cnt + ];
cnt += ;
}
void init(void)
{
cnt = ;
memset(Edge, , sizeof(Edge));
src = , sink = ;
ndot = *n+*m+;
}
void update(void)
{
for(int i = ; i < cnt; i++)
E[i] = BE[i];
for(int i = ; i <= n; i++)
{
int u, v;
for(EDGE *p = Edge[*i^]; p; p = p->next)
{
u = i, v = p->i/ - n;
if(rank1[u][v] >= mi && rank1[u][v] <= mx)
p->c = ;
else p->c = ;
}
}
}
void bfs(void)
{
queue<int> q;
q.push(sink);
vis[sink] = ;
Now[] = ;
while(!q.empty())
{
int u = q.front();
int v;
q.pop();
for(EDGE *p = Edge[u]; p; p = p->next)
if(!vis[v = p->i] && p->ani->c)
{
vis[v] = ;
dfn[v] = dfn[u] + ;
Now[dfn[v]]++;
q.push(v);
}
}
}
int ISAP(int s, int end, int flow)
{
if(s == end)
return flow;
int i, tab = ndot -, now = , vary;
for(EDGE *p = Edge[s]; p && flow; p = p->next)
if(p->c)
{
if(dfn[s] == dfn[i = p->i] + )
vary = ISAP(i, end, min(flow, p->c)),
p->c -= vary, p->ani->c += vary, now +=vary, flow -= vary;
if(p->c)
tab = min(tab, dfn[i]);
if(dfn[src] == ndot)
return now;
}
if(now == )
{
if(--Now[dfn[s]] == )
dfn[src] = ndot;
++Now[dfn[s] = tab + ];
}
return now;
}
int max_flow(int s, int end)
{
int ret = ;
memset(Now, , sizeof(Now));
memset(dfn, , sizeof(dfn));
// bfs();
Now[] = ndot;
for(; dfn[s] < ndot;)
ret += ISAP(s, end, inf);
return ret;
}
int main(void)
{ scanf("%d%d", &n, &m);
init();
for(int i = ; i <= n; i++)
{
for(int j = ; j <= m; j++)
{
int x;
scanf("%d", &x);
rank1[i][x] = j;
add(*i^, *(j+n), , E[cnt], E[cnt + ]);
}
add(src, *i, inf, E[cnt], E[cnt + ]);
add(*i, *i^, , E[cnt], E[cnt + ]);
}
for(int i = ; i <= m; i++)
{
scanf("%d", cap + i);
add(*(i+n), *(i+n)^, cap[i], E[cnt], E[cnt + ]);
add(*(i+n)^, sink, inf, E[cnt], E[cnt + ]);
}
int l = , r = m, mid;
// mx =m, mi = 1; int ans = m;
while(l <= r)
{
mid = (l + r)>>;
int flag = ;
for(mi = , mx = mid; mx <= m; mx++, mi++)
{
update();
if(max_flow(src, sink) == n)
{
int temp = mid;
ans = min(temp, ans);
flag = ;
break;
}
}
if(flag)
r = mid-;
else l = mid + ; }
printf("%d\n", ans);
return ;
}

POJ 2289 Jamie's Contact Groups & POJ3189 Steady Cow Assignment的更多相关文章

  1. POJ 2289 Jamie's Contact Groups / UVA 1345 Jamie's Contact Groups / ZOJ 2399 Jamie's Contact Groups / HDU 1699 Jamie's Contact Groups / SCU 1996 Jamie's Contact Groups (二分,二分图匹配)

    POJ 2289 Jamie's Contact Groups / UVA 1345 Jamie's Contact Groups / ZOJ 2399 Jamie's Contact Groups ...

  2. Poj 2289 Jamie's Contact Groups (二分+二分图多重匹配)

    题目链接: Poj 2289 Jamie's Contact Groups 题目描述: 给出n个人的名单和每个人可以被分到的组,问将n个人分到m个组内,并且人数最多的组人数要尽量少,问人数最多的组有多 ...

  3. poj 2289 Jamie's Contact Groups【二分+最大流】【二分图多重匹配问题】

    题目链接:http://poj.org/problem?id=2289 Jamie's Contact Groups Time Limit: 7000MS   Memory Limit: 65536K ...

  4. POJ 2289——Jamie's Contact Groups——————【多重匹配、二分枚举匹配次数】

    Jamie's Contact Groups Time Limit:7000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I ...

  5. POJ 2289 Jamie's Contact Groups 二分图多重匹配 难度:1

    Jamie's Contact Groups Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 6511   Accepted: ...

  6. POJ 2289 Jamie's Contact Groups (二分+最大流)

    题目大意: 有n个人,可以分成m个组,现在给出你每个人可以去的组的编号,求分成的m组中人数最多的组最少可以有多少人. 算法讨论: 首先喷一下这题的输入,太恶心了. 然后说算法:最多的最少,二分的字眼. ...

  7. 图论--网络流--最大流 POJ 2289 Jamie's Contact Groups (二分+限流建图)

    Description Jamie is a very popular girl and has quite a lot of friends, so she always keeps a very ...

  8. POJ 2289 Jamie's Contact Groups(多重匹配+二分)

    题意: Jamie有很多联系人,但是很不方便管理,他想把这些联系人分成组,已知这些联系人可以被分到哪个组中去,而且要求每个组的联系人上限最小,即有一整数k,使每个组的联系人数都不大于k,问这个k最小是 ...

  9. POJ 2289 Jamie's Contact Groups

    二分答案+网络最大流 #include<cstdio> #include<cstring> #include<cmath> #include<vector&g ...

随机推荐

  1. MVC 表单提交提示:已添加了具有相同键的项。

    MVC:页面提交的时候报如下错误: 解决方案: 这个Model 里面定义了重复的字段so~~~

  2. C#3.0 集合

    实现IEnumerable<T>伴随一个迭代: public class MyGenCollection : IEnumerable<int> { int[] data = { ...

  3. SQL SERVER 锁定的实例

    ---实例DB:AdventureWorks2014 --- 创建view DBLocks USE [AdventureWorks2014] GO /****** Object: View [dbo] ...

  4. Apache 流媒体 拖动模块编译

    Windows使用apxs独立编译 Apache 模块 http://blog.sina.com.cn/s/blog_43b83d340100mdhl.html 安装 apxs 1.解压apxs.zi ...

  5. Jquery中Ajax异步请求中的async参数的作用

    之前不知道这个参数的作用,上网找了前辈的博客,在此收录到自己的博客,希望能帮到更多的朋友: test.html <a href="javascript:void(0)" on ...

  6. 九度OJ 1497 面积最大的全1子矩阵 -- 动态规划

    题目地址:http://ac.jobdu.com/problem.php?pid=1497 题目描述: 在一个M * N的矩阵中,所有的元素只有0和1,从这个矩阵中找出一个面积最大的全1子矩阵,所谓最 ...

  7. 九度OJ 1207 质因数的个数

    题目地址:http://ac.jobdu.com/problem.php?pid=1207 题目描述: 求正整数N(N>1)的质因数的个数. 相同的质因数需要重复计算.如120=2*2*2*3* ...

  8. NSInteger 与 NSUInteger 和 int与 NSInteger 区别(转)

    转自:http://blog.csdn.net/duxinfeng2010/article/details/7606261 先说说NSInteger 与 NSUInteger,在看书上代码是遇见NSI ...

  9. Sublime Text 3插件安装方法

    安装Sublime Tex 3t插件的方法: 按快捷键Ctrl + ~ 调出console 粘贴以下代码到console并回车: import urllib.request,os; pf = 'Pac ...

  10. linux 源码安装软件原理

    make 与 configure 在使用类似 gcc 的编译器来进行编译的过程并不简单,因为一套软件并不会仅有一支程序,而是有一堆程序码文件.所以除了每个主程序与副程序均需要写上一笔编译过程的命令外, ...