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

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. 【转】MyBatis学习总结(一)——MyBatis快速入门

    [转]MyBatis学习总结(一)——MyBatis快速入门 一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC ...

  2. 常用meta整理【转载】

    < meta > 元素 概要 标签提供关于HTML文档的元数据.元数据不会显示在页面上,但是对于机器是可读的.它可用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 we ...

  3. CDN的原理及对SEO的影响

    http://www.williamlong.info/archives/4059.html CDN的概念最早于1995年由美国麻省理工大学提出,是一套能够实现用户就近访问的网络解决方案.具体方法是: ...

  4. intellij idea社区版 & maven & git & tomcat/jetty 的struts2项目的搭建

    1.新建一个project,并在project下新建一个maven module.

  5. python拆分excel脚本

    因为需要将一个很大的excel按500条拆分为多个excel,手工操作实在太麻烦,就写了个python小脚本,现在是分为了多个sheet页,使用者可根据自己实际情况修改成多个文件的形式 #!/usr/ ...

  6. Oracle PL/SQL 多重选择句

    Oracle中语句块的基本格式: declare --变量定义,初始化赋值. begin --变量的赋值,函数调用,if,while等. end: Oracle中的语句:关系运算符:= <> ...

  7. [openMP] OpenMP在visual studio和mac上的配置

    今天弄了半天才弄好mac上的openmp,一方面智商下限,另一方面竟然发现网上也没有什么详细过程,特意把我的配置过程贴上来 多核编程可以认为是对多线程编程做了一定程度的抽象,提供一些简单的API,使得 ...

  8. 实习笔记-2:sql 分组不一定要group by

    今天在公司写代码的时候,遇到一个sql语句构建问题. 情形是这样的: 我需要获取不同小组下前N条记录. select top 10 * from dbo.Topic where GroupID in ...

  9. PHP中使用curlL实现GET和POST请求的方法

    基本结构 (1)初始化 curl_init() (2)设置变量 curl_setopt() .最为重要,一切玄妙均在此.有一长串cURL参数可供设置,它们能指定URL请求的各个细节.要一次性全部看完并 ...

  10. 【pano2vr】网页Flash中简单实现炫酷的3D模型制作

    花了两天时间学习如何能够高效的实现3D模型效果,毕竟是从0开始学习,感觉pano2vr这款软件挺容易上手,并且可以很容易实现简单的热点交互,可以根据交互需求设置皮肤,故将这一款软件推荐给大家: 1.简 ...