POJ 2289 Jamie's Contact Groups & POJ3189 Steady Cow Assignment
这两道题目都是多重二分匹配+枚举的做法,或者可以用网络流,实际上二分匹配也就实质是网络流,通过枚举区间,然后建立相应的图,判断该区间是否符合要求,并进一步缩小范围,直到求出解。不同之处在对是否满足条件的判断,可以求最大流或者最大匹配看匹配数目是否满足题意。
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的更多相关文章
- 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 ...
- Poj 2289 Jamie's Contact Groups (二分+二分图多重匹配)
题目链接: Poj 2289 Jamie's Contact Groups 题目描述: 给出n个人的名单和每个人可以被分到的组,问将n个人分到m个组内,并且人数最多的组人数要尽量少,问人数最多的组有多 ...
- poj 2289 Jamie's Contact Groups【二分+最大流】【二分图多重匹配问题】
题目链接:http://poj.org/problem?id=2289 Jamie's Contact Groups Time Limit: 7000MS Memory Limit: 65536K ...
- POJ 2289——Jamie's Contact Groups——————【多重匹配、二分枚举匹配次数】
Jamie's Contact Groups Time Limit:7000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I ...
- POJ 2289 Jamie's Contact Groups 二分图多重匹配 难度:1
Jamie's Contact Groups Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 6511 Accepted: ...
- POJ 2289 Jamie's Contact Groups (二分+最大流)
题目大意: 有n个人,可以分成m个组,现在给出你每个人可以去的组的编号,求分成的m组中人数最多的组最少可以有多少人. 算法讨论: 首先喷一下这题的输入,太恶心了. 然后说算法:最多的最少,二分的字眼. ...
- 图论--网络流--最大流 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 ...
- POJ 2289 Jamie's Contact Groups(多重匹配+二分)
题意: Jamie有很多联系人,但是很不方便管理,他想把这些联系人分成组,已知这些联系人可以被分到哪个组中去,而且要求每个组的联系人上限最小,即有一整数k,使每个组的联系人数都不大于k,问这个k最小是 ...
- POJ 2289 Jamie's Contact Groups
二分答案+网络最大流 #include<cstdio> #include<cstring> #include<cmath> #include<vector&g ...
随机推荐
- 存储结构中的对齐(alignment)
最近,在测试基于ceph的小文件合并方案(见上个博文)时,遇到一个怪异的现象:将librados提供的append接口与我们封装的WriteFullObj接口(osd端是append操作和kvdb的p ...
- scala中的call-by-name和call-by-value
http://www.jianshu.com/p/93eefcb61d4f val和def的区别 在scala中,可以用val和def前缀来定义变量,例如: val x = 1 def y = &qu ...
- Html5时钟的实现
最近准备把自己的博客装修一下,首先,先为自己设计一个时钟吧,希望博客园能够尽快发放给我使用js的权限! 自从看见了苹果设计的那款因为侵权而赔钱了时钟,我就决定我的时钟一定是要参考这个来设计了! 不得不 ...
- Android线控的使用
实现方式一:只能在程序为前台时监控 在Activity中即可监听 @Override public boolean onKeyUp(int keyCode, KeyEvent event) { Log ...
- freemarker.core.InvalidReferenceException: Expression stackObject.value.get(propertyName).toString() is undefined
很奇怪的报错, 在实体中添加 toString方法后, 想在前台列表中使用 <s:debug标签调试, 发现报错如下: freemarker.core.InvalidReferenceExcep ...
- MySql数据库的导入_命令工具
一.如何导入别人已经建好的数据库 create database goods use goods source E:\goods.sql (绝对路径) 这样就导入了指定的数据库到本机电脑 二.任何数据 ...
- android 电话拨号器
电话拨号器(重点) 1.产品经理: 需求分析文档,设计原型图 2.UI工程师: 设计UI界面 3.架构师: 写架构,接口文档 4.码农: 服务端,客户端 ...
- 代码版本管理/SVN/Git
代码版本管理 一.SVN 1.SVN diff(create patch) 遇到了一个问题: Index: 通信协议.doc ===================================== ...
- DLL详解及Denpendcy Walker的使用
下面的文章被N次转载,为了尊重原作,\(^o^)/~,贴出最早发布这篇文章的地址及作者. 动态链接库 Windows的活动大陆 2006-07-26 09:21 作者:狂ρκ来源:电脑爱好者 在 ...
- 第30条:用enum代替int常量
在java1.5之前,表示枚举类型的常用模式是声明一组具名的int常量,每个类型成员一个常量: public static final int APPLE_FUJI = 0; public stati ...