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 ...
随机推荐
- foo,bar,baz
https://en.wikipedia.org/wiki/Foobar 原文: The terms foobar, foo, bar, baz and qux are sometimes used ...
- Ceph Newstore存储引擎介绍
在Ceph被越来越多地应用于各项存储业务过程中,其性能及调优策略也成为用户密切关注讨论的话题,影响性能表现关键因素之一即OSD存储引擎实现:Ceph基础组件RADOS是强一致.对象存储系统,其OSD底 ...
- Beyond Compare 相同文件对比结果仍显示红色 解决方案
转载:http://blog.sina.com.cn/s/blog_4d4bc1110100zj7x.html 1. 问题详细描述如下. 下图显示对比结果中,两侧的aaa.xml是一模一样,会话中 ...
- 全局负载均衡GSLB之“部署篇”
http://virtualadc.blog.51cto.com/3027116/875622 前言 随着web应用的不断发展,客户对于业务的稳定性.可靠性等也提出更高的要求,已不再局限于IDC内部的 ...
- redirect_uri参数错误解决方法
坑,微信改来改去的,找死人了,以前在“开发者中心”中,现在改在”接口权限“中了.
- C#微信开发之旅--准备阶段
最近才开始学微信开发的相关内容,记录下,慢慢的养成习惯! 1.申请公众号: 公众号分为 订阅号 和 服务号.他们之前的区别可以点击这里查看 因为我们是测试的,所以可以直接申请测试帐号,就把所有的功能都 ...
- 利用css3动画和border来实现圆形进度条
最近在学习前端的一些知识,发现border的功能十分强大啊! 首先来看看demo 就是这么一个圆形的进度条,在文本框中输入0-100的数值下面的进度条相应的转到多少 这个主要是利用border,旋转和 ...
- 在 Eclipse 中使用 JSHint 检查 JavaScript 代码
JSHint Home: http://www.jshint.com/ JSHint Options: http://www.jshint.com/options/ JSHint For Eclips ...
- Mysql的联合查询
联合查询 union联合查询 语法: select 语句 union [all|distinct] select 语句; 示例: 特点: 条件:两表的查询出来的字段数目必须相同 ...
- 责任链模式(Chain of Responsibility Pattern)
责任链模式:可以为某个请求创建一个对象链.每个对象依序检查此请求,并对其处理,或者把它传给链中的下一个对象. 责任链上的对象负责处理请求,客户只需要将请求发送到责任链上即可,无需关心处理的细节和请求的 ...