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

牛棚个数最多为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. 面试题之——抽象类(abstract class)与接口(interface)的区别

    抽象类可以有构造方法,接口中不能有构造方法.(虽然抽象类有构造方法,但它也不能被实例化) 抽象类中可以有普通成员变量,接口中没有普通成员变量. 抽象类和接口中都可以包含静态成员变量.抽象类中的静态成员 ...

  2. SDUT 2860-生日Party(BFS)

    生日Party Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描写叙述 Sherlock的生日即将来临,Sherlock打算邀请几个好 ...

  3. WCF技术剖析之十一:异步操作在WCF中的应用(下篇)

    原文:WCF技术剖析之十一:异步操作在WCF中的应用(下篇) 说完了客户端的异步服务调用(参阅WCF技术剖析之十一:异步操作在WCF中的应用(上篇)),我们在来谈谈服务端如何通过异步的方式为服务提供实 ...

  4. perl 为什么要用引用来做对象呢?

    perl 为什么要用引用来做对象呢? 因为一个重要的原因是 my 引用 脱离作用域,外部仍旧生效

  5. lua 与 php 通过AES数据加密进行通讯

    近期公司有款<围住神经猫>的微信小游戏火爆的不行!公司又决定开发一系列的神经猫的小游戏,于是,我被拉过来了. 后来使用cocos-2dx 开发一款小游戏,client用的是lua脚本,为了 ...

  6. javaee加密部署,tomcat使用自己的classloader解密【正解】

    [起因] 公司需要对一个web项目进行加密之后出售, 大家都知道的,class很好反编译, 所以需要对class文件先进行加密, 然后使用自己的classloader进行解密并加载. [步骤] 大概分 ...

  7. QSettings操作配置文件

    用Qt写界面时,难免会进行本地信息的保存,可以使用轻量级数据库sqlite,也可以使用QSettings读写配置文件.     如何来进行读写呢?如下,使用QSettings写一个通用的读写方法:   ...

  8. delphiXE调用Objective-c库

    http://stackoverflow.com/questions/16515218/xe4-firemonkey-ios-static-library-pascal-conversion-from ...

  9. vld(Visual Leak Detector) 内存泄露检测工具

    初识Visual Leak Detector 灵活自由是C/C++语言的一大特色,而这也为C/C++程序员出了一个难题.当程序越来越复 杂时,内存的管理也会变得越加复杂,稍有不慎就会出现内存问题.内存 ...

  10. awakeFromNib小总结

    awakeFromNib 在使用IB的时候才会涉及到此方法的使用,当.nib文件被载入的时候,会发送一个awakeFromNib的消息到.nib文件里的每一个对象,每一个对象都能够定义自己的awake ...