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

牛棚个数最多为20,那么直接枚举最差排名和最好排名,对于每种情况判断是否合法,取最小值。

构图:

源点与每头牛之间连接一条边,边权为1,每头牛与枚举范围内的牛棚之间连接一条边,边权为1(表示每头牛可以入住的牛棚),然后每个牛棚与汇点之间建立一条边,边权为每个牛棚的入住上限。

换了一个模板,那个Dinic模板用邻接矩阵存储的,速度太慢了。这个模板非常优秀,只是有点长了。

#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
#define N 1200
#define M 50220
#define INF 0x3f3f3f3f class MaxFlow {
public:
struct record {
int v, f, next;
} edge[M];
int n, s, t;
int pos[N], dis[N], vh[N], cl;
int his[N], di[N], pre[N]; void AddEdge(int a, int b, int f) {
cl++;
edge[cl].next = pos[a];
edge[cl].v = b;
edge[cl].f = f;
pos[a] = cl;
cl++;
edge[cl].next = pos[b];
edge[cl].v = a;
edge[cl].f = 0; //若为无向边,则f = f
pos[b] = cl;
}
void Init() {
cl = 1;
memset(dis, 0, sizeof(dis));
memset(vh, 0, sizeof(vh));
memset(pos, 0, sizeof(pos));
}
int flow() {
vh[0] = n; //初始化GAP数组(默认所有点的距离标号均为0,则距离标号为0的点数量为n)
for (int i = 0; i < n; i++) di[i] = pos[i]; //初始化当前弧
int i = s, aug = INF, flow = 0; //初始化一些变量,flow为全局流量,aug为当前增广路的流量
bool flag = false; //标记变量,记录是否找到了一条增广路(若没有找到则修正距离标号)
while (dis[s] < n) {
his[i] = aug; //保存当前流量
flag = false;
for (int p=di[i]; p; p=edge[p].next)
if ((edge[p].f > 0) && (dis[edge[p].v] + 1 == dis[i])) {//利用距离标号判定可行弧
flag = true; //发现可行弧
di[i] = p; //更新当前弧
aug = min(aug, edge[p].f); //更新当前流量
pre[edge[p].v] = p; //记录前驱结点
i = edge[p].v; //在弧上向前滑动
if (i == t) {//遇到汇点,发现可增广路
flow += aug; //更新全局流量
while (i != s) {//减少增广路上相应弧的容量,并增加其反向边容量
edge[pre[i]].f -= aug;
edge[pre[i]^1].f += aug;
i = edge[pre[i]^1].v;
}
aug = INF;
}
break;
}
if (flag) continue; //若发现可行弧则继续,否则更新标号
int min = n - 1;
for (int p=pos[i]; p; p=edge[p].next)
if ((edge[p].f > 0) && (dis[edge[p].v] < min)) {
di[i] = p; //不要忘了重置当前弧
min = dis[edge[p].v];
} --vh[dis[i]];
if (vh[dis[i]] == 0) break; //更新vh数组,若发现距离断层,则算法结束(GAP优化)
dis[i] = min + 1;
++vh[dis[i]];
if (i != s) {//退栈过程
i = edge[pre[i]^1].v;
aug = his[i];
}
}
return flow;
}
} net; int n, b, g[1002][22], s[22]; void init(int x, int y) {
net.Init(); net.s = 0, net.t = n+b+1, net.n = n+b+2;
for (int i=1; i<=n; i++) net.AddEdge(0, i, 1);
for (int i=1; i<=n; i++) for (int j=x; j<=y; j++)
net.AddEdge(i, g[i][j]+n, 1);
for (int i=1; i<=b; i++) net.AddEdge(n+i, net.t, s[i]);
}
int main() {
scanf("%d%d", &n, &b);
for (int i=1; i<=n; i++) for (int j=1; j<=b; j++) scanf(" %d", &g[i][j]);
for (int i=1; i<=b; i++) scanf("%d", &s[i]);
int ans = INF; for (int i=1; i<=b; i++) for (int j=i; j<=b; j++) {
init(i, j);
if (net.flow() == n) ans = min(ans, j-i+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——————【多重匹配、二分枚举区间长度】

     Steady Cow Assignment Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I ...

  3. POJ 3189 Steady Cow Assignment

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

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

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

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

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

  6. POJ3189 Steady Cow Assignment

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

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

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

  8. POJ 2289 Jamie's Contact Groups & POJ3189 Steady Cow Assignment

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

  9. Steady Cow Assignment POJ - 3189 (最大流+匹配)

    Farmer John's N (1 <= N <= 1000) cows each reside in one of B (1 <= B <= 20) barns which ...

随机推荐

  1. virtualbox从.VDI备份文件新建/恢复虚拟机(包括恢复各个备份节点)

    一.前言: ubuntu上的virtualbox中的虚拟机如果关机不当会导致整个虚拟机坏掉,而且采用各种debug方式都难以让它重新启动.这时你只能用之前备份的各个VDI文件来恢复系统了.还有另一种场 ...

  2. Docker学习笔记(1) — docker 常用命令

    1. docker version显示 Docker 版本信息.2. docker info显示 Docker 系统信息,包括镜像和容器数.3. docker searchdocker search ...

  3. Swift - 经纬度位置坐标与真实地理位置相互转化

    通过CoreLocation类,得到的定位信息都是以经度和纬度等表示的地理信息,通过CLGeocoder类可以将其反编码成一个地址.反之,也可根据一个地址获取经纬度. 1,通过经纬度获取地址 1 2 ...

  4. EasyUI - SplitButton 分割按钮

    效果: html代码: <!--使用标签创建,直接使用即可,不必使用js代码--> <%--<a href="javascript:void(0)" id= ...

  5. PL/SQL(二):变量

    变量 标识符定义 PL/SQL程序设计中的标识符定义与SQL的标识符定义的要求相同.要求和限制有: 个字符. )首字符必须为字母. )不区分大小写. )不能使用SQL保留字. )对标识符的命名最好遵循 ...

  6. jquery mobile -role

    jquery mobile -role - cc_jony - 博客园 jquery mobile -role   data-page 页面 data-header 页面的头部 data-conten ...

  7. 如何在SourceInsight中选中匹配的大括号中的内容

    如何在SourceInsight中选中匹配的大括号中的内容 要分析的代码很长,多个for,if等分析嵌套在一起,代码有点乱,找到了这个分支的头,却不知道尾在哪,找到了尾却不知道哪是开头,在网上找了一下 ...

  8. Linux下使用Mysql

    一.连接MySQL数据库 一个最简单的程序示例: #include <stdio.h> #include "mysql.h" int main() { MYSQL my ...

  9. 使用hadoop ecipse插件须要注意的问题

    1.关于run on hadoop的问题: 在未用hadoop eclipse插件前,我以为通过hadoop eclipse 插件不但能够管理hdfs,还能够自己主动打包程序.并帮我自己主动设置Con ...

  10. MySql自己定义排序

    查询语句: select id,name,stauts from special where id in (50,51,52,53,54,55) order by FIELD( id ,51,50, ...