Steady Cow Assignment

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Description

Farmer John's N (1 <= N <= 1000) cows each reside in one of B (1 <= B <= 20) barns which, of course, have limited capacity. Some cows really like their current barn, and some are not so happy.

FJ would like to rearrange the cows such that the cows are as equally happy as possible, even if that means all the cows hate their assigned barn.

Each cow gives FJ the order in which she prefers the barns. A cow's happiness with a particular assignment is her ranking of her barn. Your job is to find an assignment of cows to barns such that no barn's capacity is exceeded and the size of the range (i.e., one more than the positive difference between the the highest-ranked barn chosen and that lowest-ranked barn chosen) of barn rankings the cows give their assigned barns is as small as possible.

Input

Line 1: Two space-separated integers, N and B

Lines 2..N+1: Each line contains B space-separated integers which are exactly 1..B sorted into some order. The first integer on line i+1 is the number of the cow i's top-choice barn, the second integer on that line is the number of the i'th cow's second-choice barn, and so on.

Line N+2: B space-separated integers, respectively the capacity of the first barn, then the capacity of the second, and so on. The sum of these numbers is guaranteed to be at least N.

Output

Line 1: One integer, the size of the minumum range of barn rankings the cows give their assigned barns, including the endpoints.

Sample Input

6 4
1 2 3 4
2 3 1 4
4 2 3 1
3 1 2 4
1 3 4 2
1 4 2 3
2 1 3 2

Sample Output

2

Hint

Explanation of the sample:

Each cow can be assigned to her first or second choice: barn 1 gets cows 1 and 5, barn 2 gets cow 2, barn 3 gets cow 4, and barn 4 gets cows 3 and 6.

 
 
题目大意:给你N表示有N头牛,B表示有B个牛棚。下边N*B的矩阵A,N行,表示N头牛,B列表示喜爱排名从高到低。那么A(i,j)表示第i头牛喜欢排名为j的是哪个牛棚,最后一行为每个牛棚能装多少头牛。数据保证N头牛一定能都安排到牛棚中。现在让你求最小的排名区间长度。
 
解题思路:一对多,多重匹配。二分枚举区间长度,同时枚举排名左端点和排名右端点。如果匹配成功,说明这个区间长度是可以的,记录答案,同时向小逼近,如果不成功,向大逼近。
 
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1100;
int Map[maxn][maxn];
int linker[maxn][maxn], used[maxn], cap[maxn];
bool dfs(int u,int rn,int st,int en){
for(int v = 1; v <= rn; v++){
if(used[v] ){
continue;
}
if(Map[u][v] > en || Map[u][v] < st){
continue;
}
used[v] = 1;
if(linker[v][0] < cap[v]){
linker[v][++linker[v][0]] = u;
return true;
}else{
for(int j = 1; j <= linker[v][0]; j++){
if(dfs(linker[v][j],rn,st,en)){
linker[v][j] = u;
return true;
}
}
}
}
return false;
}
bool Hungary(int ln,int rn,int mid){
int en ;
for(int st = 1; st <= rn -mid + 1; st++){
en = st + mid - 1;
int ret = 0;
for(int i = 0; i <= rn; i++){
linker[i][0] = 0;
}
for(int i = 1; i <= ln; i++){
memset(used,0,sizeof(used));
if(dfs(i,rn,st,en)){
ret++;
}
}
if(ln == ret){
return true;
}
}
return false;
}
int main(){
int N, B;
int matrix[1200][50];
while(scanf("%d%d",&N,&B)!=EOF){
int c;
for(int i = 1; i <= N; i++){
for(int j = 1; j <= B; j++){
scanf("%d",&c);
Map[i][c] = j;
}
}
for(int i = 1; i <= B; i++){
scanf("%d",&cap[i]);
}
int l = 1, r = B, ans;
while(l <= r){
int mid = (l+r)/2;
if(Hungary(N,B,mid)){
r = mid -1;
ans = mid;
}else{
l = mid + 1;
}
}
printf("%d\n",ans);
}
return 0;
}

  

还有一种最开始想到的,每次枚举,每次建图,而不是限制区间,时间没有上面的快,但是更好理解。

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
const int INF = 9999999;
const int maxn = 1100;
int Map[maxn][maxn];
int linker[maxn][maxn], used[maxn], cap[maxn];
bool dfs(int u,int rn){
for(int v = 1; v <= rn; v++){
if(used[v] || !Map[u][v]){
continue;
}
used[v] = 1;
if(linker[v][0] < cap[v]){
linker[v][++linker[v][0]] = u;
return true;
}else{
for(int j = 1; j <= linker[v][0]; j++){
if(dfs(linker[v][j],rn)){
linker[v][j] = u;
return true;
}
}
}
}
return false;
}
bool Hungary(int ln,int rn){
int ret = 0;
for(int i = 0; i <= rn; i++){
linker[i][0] = 0;
}
for(int i = 1; i <= ln; i++){
memset(used,0,sizeof(used));
if(dfs(i,rn)){
ret++;
}
}
if(ln == ret){
return true;
}
return false;
}
int main(){
int N, B;
int matrix[1200][50];
while(scanf("%d%d",&N,&B)!=EOF){
for(int i = 1; i <= N; i++){
for(int j = 1; j <= B; j++){
scanf("%d",&matrix[i][j]);
}
}
for(int i = 1; i <= B; i++){
scanf("%d",&cap[i]);
}
int l = 1, r = B, ans;
while(l <= r){
int mid = (l+r)/2;
int flag = 0;
for(int i = 1; i <= B - mid + 1; i++){
memset(Map,0,sizeof(Map));
for(int j = 1; j <= N; j++){
for(int k = i; k < i + mid; k++){
Map[j][matrix[j][k]] = 1;
}
}
if(Hungary(N,B)){
flag = 1; break;
}
}
if(flag){
r = mid - 1;
ans = mid;
}else{
l = mid + 1;
}
}
printf("%d\n",ans); }
return 0;
}

  

 

POJ 3189——Steady Cow Assignment——————【多重匹配、二分枚举区间长度】的更多相关文章

  1. Poj 3189 Steady Cow Assignment (多重匹配)

    题目链接: Poj 3189 Steady Cow Assignment 题目描述: 有n头奶牛,m个棚,每个奶牛对每个棚都有一个喜爱程度.当然啦,棚子也是有脾气的,并不是奶牛想住进来就住进来,超出棚 ...

  2. POJ 3189 Steady Cow Assignment 【二分】+【多重匹配】

    <题目链接> 题目大意: 有n头牛,m个牛棚,每个牛棚都有一定的容量(就是最多能装多少只牛),然后每只牛对每个牛棚的喜好度不同(就是所有牛圈在每个牛心中都有一个排名),然后要求所有的牛都进 ...

  3. POJ 3189 Steady Cow Assignment

    题意:每个奶牛对所有的牛棚有个排名(根据喜欢程度排的),每个牛棚能够入住的牛的数量有个上限,重新给牛分配牛棚,使牛棚在牛心中的排名差(所有牛中最大排名和最小排名之差)最小.   题目输入: 首先是两个 ...

  4. POJ 3189 Steady Cow Assignment【网络流】

    题意:每个奶牛对所有的牛棚有个排名(根据喜欢程度排的),每个牛棚能够入住的牛的数量有个上限,重新给牛分配牛棚,使牛棚在牛心中的排名差(所有牛中最大排名和最小排名之差)最小. 牛棚个数最多为20,那么直 ...

  5. POJ 2112 Optimal Milking(Floyd+多重匹配+二分枚举)

    题意:有K台挤奶机,C头奶牛,每个挤奶机每天只能为M头奶牛服务,下面给的K+C的矩阵,是形容相互之间的距离,求出来走最远的那头奶牛要走多远   输入数据: 第一行三个数 K, C, M  接下来是   ...

  6. HDU 1669 Jamie's Contact Groups(多重匹配+二分枚举)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1669 题目大意: 给你各个人可以属于的组,把这些人分组,使这些组中人数最多的组人数最少,并输出这个人数 ...

  7. POJ3189:Steady Cow Assignment(二分+二分图多重匹配)

    Steady Cow Assignment Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7482   Accepted: ...

  8. POJ3189 Steady Cow Assignment —— 二分图多重匹配/最大流 + 二分

    题目链接:https://vjudge.net/problem/POJ-3189 Steady Cow Assignment Time Limit: 1000MS   Memory Limit: 65 ...

  9. POJ 2289(多重匹配+二分)

    POJ 2289(多重匹配+二分) 把n个人,分到m个组中.题目给出每一个人可以被分到的那些组.要求分配完毕后,最大的那一个组的人数最小. 用二分查找来枚举. #include<iostream ...

随机推荐

  1. 【C#】EF学习<一> CodeFist

    [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) 目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) http://www.cnblogs.com/ ...

  2. C#中工厂模式的作用

    1.比如,主要用于对扩展性有要求的功能. 以简单工厂为例: 接口Fun有三个实现 class FunA FunB FunC工厂 class Fac {   public static Fun getF ...

  3. pg10.1 orafce3.6 安装

    安装unzip orafce-mastermv orafce-master /opt/soft_bak/postgresql-10.1/contribcd /opt/soft_bak/postgres ...

  4. html之表单和简单CSS

    一.==表单== 1. form表单本身 <form name="myform" action="#" method="get"> ...

  5. git基础命令整理

    首先安装git,然后选择一个文件夹做初始化!! yum -y install git                        ### 安装 git init                    ...

  6. Mybatis学习笔记(二) —— mybatis入门程序

    一.mybatis下载 mybaits的代码由github.com管理,下载地址:https://github.com/mybatis/mybatis-3/releases 下载完后的目录结构: 二. ...

  7. dropzone手动上传

    html: <div class="field"> <div id="file" class="dropzone"> ...

  8. Linux内核硬件访问技术

    ① 驱动程序控制设备,主要是通过访问设备内的寄存器来达到控制目的.因此我们讨论如何访问硬件,就成了如何访问这些寄存器. ② 在Linux系统中,无论是内核程序还是应用程序,都只能使用虚拟地址,而芯片手 ...

  9. Java类名 方法名 常量 变量的命名习惯

    1.包 用于将完成不同功能的类分门别类,放在不同的目录(包)下,包的命名规则:将公司域名反转作为包名,对于包名,每个字母都需要小写. 如果定义类的时候没有使用package(包),那么java就认为我 ...

  10. hadoop单机配置

    条件: 先下载VMware1.2,然后安装. 下载ubuntu-1.4.05-desktop-amd64.iso.下载地址:http://mirrors.aliyun.com/ubuntu-relea ...