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 ...
随机推荐
- PHP之基本语法
人生最幸福的事之一就是,邻居家的wifi密码是123456789,于是回家在pad上也照样可以扯淡.任何语言都有自己的语法,这里只简单说些我觉得应该注意的地方. 首先要明白,PHP是运行于服务器端的脚 ...
- C#JSON格式数据的转换
json格式字符串转化为json对象:JObject calculate = (JObject)JsonConvert.DeserializeObject(Rep.Request["data ...
- C#学习笔记15:字符串、文件、目录的操作方法
字符串:不可变性 String str=”abcdf”; 将字符串转换为char数组:ToCharArray(); Char[] ch=str.ToCharAarray(); 将char数组转换为字符 ...
- 对象创建型模式------Builder(生成器)
本文系转载,转载地址http://blog.sina.com.cn/s/blog_59b6af690100zj3l.html,只供自己学习使用. 假设现在有三种产品,是玩具,都是由三部分组成,头,身体 ...
- VS2010 VS2012 如何连接Oracle 11g数据库
oracle是开发者常用的数据库,在做.NET开发是,由于Vs自带的驱动只能连接oracle 10g及以下版本,那么如何连接oracle 11g呢? 工具/原料 事先安装VS2010或者VS201 ...
- 用pelican搭建完美博客
前面有文章介绍本站采用了Python编写的Pelican静态生成博客系统, 之所以没有使用当前很火的Jekyll, 是因为它是Ruby编写, 而我又对Ruby没有啥兴趣, 所以还是选择了使用了我熟悉的 ...
- 为 Date 对象添加 ago 属性
/* * 此处,__defineGetter__与__defineSetter__相当于C#实体中类中的get与set **/ Date.prototype.__defineGetter__('ago ...
- 修改placeholder颜色
#contact_info为textarea的ID #contact_info::-webkit-input-placeholder{ color:#999;}#contact_info:-moz-p ...
- HDU 4763 (KMP算法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4763 题目大意:给定一串字符,从中找出符合“EAEBE”格式的E的最大字符数.AB可以是任意数量的任意 ...
- 用分治法实现大数乘法,加法,减法(java实现)
大数乘法即多项式乘法问题,求A(x)与B(x)的乘积C(x),朴素解法的复杂度O(n^2),基本思想是把多项式A(x)与B(x)写成 A(x)=a*x^m+b B(x)=c*x^m+d 其中a,b,c ...