POJ 3189 Steady Cow Assignment【网络流】
题意:每个奶牛对所有的牛棚有个排名(根据喜欢程度排的),每个牛棚能够入住的牛的数量有个上限,重新给牛分配牛棚,使牛棚在牛心中的排名差(所有牛中最大排名和最小排名之差)最小。
牛棚个数最多为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【网络流】的更多相关文章
- Poj 3189 Steady Cow Assignment (多重匹配)
题目链接: Poj 3189 Steady Cow Assignment 题目描述: 有n头奶牛,m个棚,每个奶牛对每个棚都有一个喜爱程度.当然啦,棚子也是有脾气的,并不是奶牛想住进来就住进来,超出棚 ...
- POJ 3189——Steady Cow Assignment——————【多重匹配、二分枚举区间长度】
Steady Cow Assignment Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I ...
- POJ 3189 Steady Cow Assignment
题意:每个奶牛对所有的牛棚有个排名(根据喜欢程度排的),每个牛棚能够入住的牛的数量有个上限,重新给牛分配牛棚,使牛棚在牛心中的排名差(所有牛中最大排名和最小排名之差)最小. 题目输入: 首先是两个 ...
- POJ 3189 Steady Cow Assignment 【二分】+【多重匹配】
<题目链接> 题目大意: 有n头牛,m个牛棚,每个牛棚都有一定的容量(就是最多能装多少只牛),然后每只牛对每个牛棚的喜好度不同(就是所有牛圈在每个牛心中都有一个排名),然后要求所有的牛都进 ...
- POJ3189:Steady Cow Assignment(二分+二分图多重匹配)
Steady Cow Assignment Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7482 Accepted: ...
- POJ3189 Steady Cow Assignment
Steady Cow Assignment Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6817 Accepted: ...
- POJ3189 Steady Cow Assignment —— 二分图多重匹配/最大流 + 二分
题目链接:https://vjudge.net/problem/POJ-3189 Steady Cow Assignment Time Limit: 1000MS Memory Limit: 65 ...
- POJ 2289 Jamie's Contact Groups & POJ3189 Steady Cow Assignment
这两道题目都是多重二分匹配+枚举的做法,或者可以用网络流,实际上二分匹配也就实质是网络流,通过枚举区间,然后建立相应的图,判断该区间是否符合要求,并进一步缩小范围,直到求出解.不同之处在对是否满足条件 ...
- Steady Cow Assignment POJ - 3189 (最大流+匹配)
Farmer John's N (1 <= N <= 1000) cows each reside in one of B (1 <= B <= 20) barns which ...
随机推荐
- 更改ORACLE 用户的 expired状态
oracle中, 经常用户的状态会变成locked, expired 等状态, 这种情况下怎么处理呢? 首先, 如果是locked状态还好办, DBA直接执行alter user scott acco ...
- 杂题_POJ上的过桥问题
本文出自:http://blog.csdn.net/svitter 过桥问题解释:一条船能够坐两个人,可是有非常多人要过河,所以送过一个人去,还有一个人还要回来接.使全部人过河之后时间最短,怎样求? ...
- sql: sybase与oracle中insert into select和select into的用法
1. sybase与oracle中insert into select和select into的用法 http://wjlvivid.iteye.com/blog/1921679 Sybase 一.首 ...
- C语言,realloc
void * realloc ( void * ptr, size_t new_size ); 关于realloc的行为方式,结合源码总结为:1. realloc失败的时候,返回NULL: 2. re ...
- Eclipse用法和技巧十六:自动添加未实现方法2
前面一篇文章里面介绍了一种常见的自动添加未实现函数的方法.这里在顺便补充几个方法.第一个方法,看上去有点怪怪的: 步骤一:Source > Clean Up: 步骤二:选择cust ...
- OCP-1Z0-042-V12.39-47题
47.Which two database operations can be performed at the mount stage of database startup? 题目解析: A和E在 ...
- How to retreive raw post data from HttpServletRequest in java
public static String getPostData(HttpServletRequest req) { StringBuilder sb = new StringBuilder(); t ...
- android调用音乐播放器,三种方
小弟想请问一下.怎样在自己写的程序中调用系统的音乐播放器呢. 我在google上搜索了.主要是有两种方法,可是都不是我想要的. 第一种是.使用mp3音乐文件的uri.和intent,进行调用.可是这样 ...
- 国际化之ResourceBundle
软件在开发时要能使它同时应对世界不同地区和国家的使用,针对不同地区和国家的访问,提供相应的,符合使用者阅读习惯的操作环境,这就必须要有国际化的概念,国际化又称为“i18n”:international ...
- Http请求工具实例编写(超长,比较清楚)
HTTP协议工作方式首先客户端发送一个请求(request)给服务器,服务器在接收到这个请求后将生成一个响应(response)返回给客户端.在这个通信的过程中HTTP协议在以下4个方面做了规定:1. ...