POJ2289 Jamie's Contact Groups —— 二分图多重匹配/最大流 + 二分
题目链接:https://vjudge.net/problem/POJ-2289
| Time Limit: 7000MS | Memory Limit: 65536K | |
| Total Submissions: 8147 | Accepted: 2736 |
Description
Input
Output
Sample Input
3 2
John 0 1
Rose 1
Mary 1
5 4
ACM 1 2 3
ICPC 0 1
Asian 0 2 3
Regional 1 2
ShangHai 0 2
0 0
Sample Output
2
2
Source
题解:
题意:jamie的QQ有n个联系人,且设置了m个分组,规定了哪些朋友可以去哪些分组。为了能够快速地找到朋友,jamie希望人数最多的分组的人数最少(最大值最小),并且满足每个朋友仅存在于一个分组中。
1.二分最大值,即每个分组的容量。
2.利用二分图多重匹配,或者最大流,求出是否所有人都可以归到一个分组中。如果可以,则减小容量,否则增大容量。
多重匹配:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <sstream>
#include <algorithm>
using namespace std;
const int INF = 2e9;
const int MOD = 1e9+;
const int MAXM = 5e2+;
const int MAXN = 1e3+; int uN, vN;
int num[MAXM], linker[MAXM][MAXN];
bool g[MAXN][MAXM], used[MAXM]; bool dfs(int u)
{
for(int v = ; v<vN; v++)
if(g[u][v] && !used[v])
{
used[v] = true;
if(linker[v][]<num[v])
{
linker[v][++linker[v][]] = u;
return true;
}
for(int i = ; i<=num[v]; i++)
if(dfs(linker[v][i]))
{
linker[v][i] = u;
return true;
}
}
return false;
} bool hungary(int mid)
{
for(int i = ; i<vN; i++)
{
num[i] = mid;
linker[i][] = ;
}
for(int u = ; u<uN; u++)
{
memset(used, false, sizeof(used));
if(!dfs(u)) return false;
}
return true;
} char tmp[];
int main()
{
while(scanf("%d%d", &uN, &vN) && (uN||vN))
{
memset(g, false, sizeof(g));
getchar();
for(int i = ; i<uN; i++)
{
gets(tmp);
int j = , len = strlen(tmp);
while(tmp[j]!=' ' && j<len) j++;
j++;
for(int v = ; j<=len; j++)
{
if(tmp[j]==' '||j==len)
{
g[i][v] = true;
v = ;
}
else v = v*+(tmp[j]-'');
}
} int l = , r = uN;
while(l<=r)
{
int mid = (l+r)>>;
if(hungary(mid))
r = mid - ;
else
l = mid + ;
}
printf("%d\n", l);
}
}
最大流:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <sstream>
#include <algorithm>
using namespace std;
const int INF = 2e9;
const int MOD = 1e9+;
const int MAXM = 5e2+;
const int MAXN = 2e3+; struct Edge
{
int to, next, cap, flow;
}edge[MAXN*MAXN];
int tot, head[MAXN]; int uN, vN, maze[MAXN][MAXN];
int gap[MAXN], dep[MAXN], pre[MAXN], cur[MAXN]; void add(int u, int v, int w)
{
edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = ;
edge[tot].next = head[u]; head[u] = tot++;
edge[tot].to = u; edge[tot].cap = ; edge[tot].flow = ;
edge[tot].next = head[v]; head[v] = tot++;
} int sap(int start, int end, int nodenum)
{
memset(dep, , sizeof(dep));
memset(gap, , sizeof(gap));
memcpy(cur, head, sizeof(head));
int u = pre[start] = start, maxflow = ,aug = INF;
gap[] = nodenum;
while(dep[start]<nodenum)
{
loop:
for(int i = cur[u]; i!=-; i = edge[i].next)
{
int v = edge[i].to;
if(edge[i].cap-edge[i].flow && dep[u]==dep[v]+)
{
aug = min(aug, edge[i].cap-edge[i].flow);
pre[v] = u;
cur[u] = i;
u = v;
if(v==end)
{
maxflow += aug;
for(u = pre[u]; v!=start; v = u,u = pre[u])
{
edge[cur[u]].flow += aug;
edge[cur[u]^].flow -= aug;
}
aug = INF;
}
goto loop;
}
}
int mindis = nodenum;
for(int i = head[u]; i!=-; i = edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap-edge[i].flow && mindis>dep[v])
{
cur[u] = i;
mindis = dep[v];
}
}
if((--gap[dep[u]])==)break;
gap[dep[u]=mindis+]++;
u = pre[u];
}
return maxflow;
} bool test(int mid)
{
tot = ;
memset(head, -, sizeof(head));
for(int i = ; i<uN; i++)
{
add(uN+vN, i, );
for(int j = ; j<vN; j++)
if(maze[i][j])
add(i, uN+j, );
}
for(int i = ; i<vN; i++)
add(uN+i, uN+vN+, mid); int maxflow = sap(uN+vN, uN+vN+, uN+vN+);
return maxflow == uN;
} char tmp[];
int main()
{
while(scanf("%d%d", &uN, &vN) && (uN||vN))
{
memset(maze, , sizeof(maze));
getchar();
for(int i = ; i<uN; i++)
{
gets(tmp);
int j = , len = strlen(tmp);
while(tmp[j]!=' ' && j<len) j++;
j++;
for(int v = ; j<=len; j++)
{
if(tmp[j]==' '||j==len)
{
maze[i][v] = ;
v = ;
}
else v = v*+(tmp[j]-'');
}
} int l = , r = uN;
while(l<=r)
{
int mid = (l+r)>>;
if(test(mid))
r = mid - ;
else
l = mid + ;
}
printf("%d\n", l);
}
}
POJ2289 Jamie's Contact Groups —— 二分图多重匹配/最大流 + 二分的更多相关文章
- 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——————【多重匹配、二分枚举匹配次数】
Jamie's Contact Groups Time Limit:7000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I ...
- POJ3189 Steady Cow Assignment —— 二分图多重匹配/最大流 + 二分
题目链接:https://vjudge.net/problem/POJ-3189 Steady Cow Assignment Time Limit: 1000MS Memory Limit: 65 ...
- POJ2112 Optimal Milking —— 二分图多重匹配/最大流 + 二分
题目链接:https://vjudge.net/problem/POJ-2112 Optimal Milking Time Limit: 2000MS Memory Limit: 30000K T ...
- POJ 2289 Jamie's Contact Groups(多重匹配+二分)
题意: Jamie有很多联系人,但是很不方便管理,他想把这些联系人分成组,已知这些联系人可以被分到哪个组中去,而且要求每个组的联系人上限最小,即有一整数k,使每个组的联系人数都不大于k,问这个k最小是 ...
- HDU 1669 Jamie's Contact Groups(多重匹配+二分枚举)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1669 题目大意: 给你各个人可以属于的组,把这些人分组,使这些组中人数最多的组人数最少,并输出这个人数 ...
- POJ2289 Jamie's Contact Groups(二分图多重匹配)
Jamie's Contact Groups Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 7721 Accepted: ...
- hdu3605 Escape 二分图多重匹配/最大流
2012 If this is the end of the world how to do? I do not know how. But now scientists have found tha ...
- Jamie's Contact Groups---hdu1669--poj2289(多重匹配+二分)
题目链接 题意:Jamie有很多联系人,但是很不方便管理,他想把这些联系人分成组,已知这些联系人可以被分到哪个组中去,而且要求每个组的联系人上限最小,即有一整数k,使每个组的联系人数都不大于k,问这个 ...
随机推荐
- MVC Remote属性验证
模型验证方式一: 1.需要添加引用: using System.Web.Mvc; 2.在模型属性上添加验证: [Remote("CheckIsHaveSerialNo", &quo ...
- hls简述(HTTP live Streaming)
hls官方地址:https://developer.apple.com/streaming/ IDR: Instantaneous Decoding Refresh (IDR) start code ...
- DBCA建库出错ORA-00600: internal error code, arguments
正常步骤安装完成Oralce,通过dbca建库,报错如下图所示: Oracle安装日志中报错如下: [Thread-40] [ 1999-12-15 12:23:54.055 CST ] [Basic ...
- Java设计模式之(工厂模式)
工厂模式: 工厂模式可以分为三类: 1)简单工厂模式(Simple Factory) 2)工厂方法模式(Factory Method) 3)抽象工厂模式(Abstract Factory) 简单工厂模 ...
- POJ2014 Flow Layout
Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 3161 Accepted: 2199 Description A f ...
- 【HDOJ6304】Chiaki Sequence Revisited(数学)
题意:给定一个序列a,定义a[1]=a[2]=1,a[n]=a[n-a[n-1]]+a[n-1-a[n-2]](n>=3),求该序列的前n项和是多少,结果对 1e9+7 取模 n<=1e1 ...
- Memcached Redis相关的干货
为了以后查阅方便,所以转了各位的博文,感谢各位原博主. http://www.searchtb.com/2011/05/redis-storage.html redis内存存储结构 ...
- BZOJ4555求和(cdq分治+NTT)
题意: 输出f(n)对998244353(7 × 17 × 223 + 1)取模的结果.1 ≤ n ≤ 100000 其中S(i,j)是第二类Stirling数,即有i个球,丢到j个盒子中,要求盒子不 ...
- 通过简单的两数相加体会hashmap的好处
目录 引入题目:两数相加 HashMap相关知识: Map集合 Map集合的特点 Map常用子类 HashMap集合 LinkedHashMap集合 Map集合的常用方法 Map集合的第一种遍历方式: ...
- java学习——关于java课件上动手动脑问题简单的分析
问题一:关于以下的代码为什么会产生错误的问题的简单分析. 第一个动手动脑提供了一下的代码,可以发现,在Foo的这个类中只定义了一个Foo(int)类型的构造函数,在之前的学习工程中,我们并没有接触到j ...