题目链接

题意

有\(N\)头牛,\(F\)个食物和\(D\)个饮料。每头牛都有自己偏好的食物和饮料列表。

问该如何分配食物和饮料,使得尽量多的牛能够既获得自己喜欢的食物又获得自己喜欢的饮料。

建图

  1. 在 源点 到 食物 之间加边,边权为\(1\)

  2. 在 饮料 到 汇点 之间加边,边权为\(1\)

  3. 将牛拆成两点,在两点之间加边,边权为\(1\)

     	这一点很重要,可以从以下两个方面去考虑:
    1) 从含义上,只要流为1,这头牛就被满足了,多了就纯属是浪费。
    2) 从操作上,最后答案是根据最大流的值来判断的,被满足的牛的数目即最大流的值。这一个判断是建立在这样一个事实上的:默认经过每头牛的流为1。因此需要拆点在中间加上限制。
    (其实第一点考虑中所说的“浪费”还是有些含糊其辞的,最合理的考虑还是第二点)
  4. 在 食物 到 喜欢它的牛(1) 之间连边,边权为\(1\)

  5. 在 喜欢它的牛(2) 到 饮料 之间连边,边权为\(1\)

Code

#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#define maxn 100010
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
struct Edge { int to, ne, c; }edge[maxn];
int dep[maxn], ne[maxn], n,f,d, tot, s,t;
void add(int u, int v, int c) {
edge[tot] = {v, ne[u], c};
ne[u] = tot++;
edge[tot] = {u, ne[v], 0};
ne[v] = tot++;
}
int bfs(int src) {
memset(dep, 0, sizeof dep);
dep[src] = 1;
queue<int> q;
while (!q.empty()) q.pop();
q.push(src);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = ne[u]; ~i; i = edge[i].ne) {
int v = edge[i].to;
if (edge[i].c > 0 && !dep[v]) dep[v] = dep[u] + 1, q.push(v);
}
}
return dep[t];
}
int dfs(int u, int flow) {
if (u == t) return flow;
int ret = 0;
for (int i = ne[u]; ~i; i = edge[i].ne) {
int v = edge[i].to;
if (edge[i].c > 0 && dep[v] == dep[u] + 1) {
int c = dfs(v, min(flow-ret, edge[i].c));
edge[i].c -= c;
edge[i^1].c += c;
ret += c;
if (ret == flow) break;
}
}
if (!flow) dep[u] = 0;
return ret;
}
int main() {
while (scanf("%d%d%d", &n, &f, &d) != EOF) {
s = 0, t = f+2*n+d+1;
tot = 0; memset(ne, -1, sizeof ne);
for (int i = 1; i <= f; ++i) add(s, i, 1);
for (int i = 1; i <= d; ++i) add(f+2*n+i, t, 1);
for (int i = 1; i <= n; ++i) {
int a,b,x;
add(f+i, f+n+i, 1);
scanf("%d%d", &a, &b);
while (a--) {
scanf("%d", &x);
add(x, f+i, 1);
}
while (b--) {
scanf("%d", &x);
add(f+n+i, f+2*n+x, 1);
}
}
int ans=0, tmp;
while (bfs(s)) {
while (tmp = dfs(s, inf)) ans += tmp;
}
printf("%d\n", ans);
}
return 0;
}

poj 3281 Dining 拆点 最大流的更多相关文章

  1. POJ 3281 Dining (拆点)【最大流】

    <题目链接> 题目大意: 有N头牛,F种食物,D种饮料,每一头牛都有自己喜欢的食物和饮料,且每一种食物和饮料都只有一份,让你分配这些食物和饮料,问最多能使多少头牛同时获得自己喜欢的食物和饮 ...

  2. POJ 3281 Dining (网络流之最大流)

    题意:农夫为他的 N (1 ≤ N ≤ 100) 牛准备了 F (1 ≤ F ≤ 100)种食物和 D (1 ≤ D ≤ 100) 种饮料.每头牛都有各自喜欢的食物和饮料, 而每种食物或饮料只能分配给 ...

  3. POJ 3281 Dining(最大流)

    POJ 3281 Dining id=3281" target="_blank" style="">题目链接 题意:n个牛.每一个牛有一些喜欢的 ...

  4. POJ 3281 Dining (网络流)

    POJ 3281 Dining (网络流) Description Cows are such finicky eaters. Each cow has a preference for certai ...

  5. poj 3281 Dining 网络流-最大流-建图的题

    题意很简单:JOHN是一个农场主养了一些奶牛,神奇的是这些个奶牛有不同的品味,只喜欢吃某些食物,喝某些饮料,傻傻的John做了很多食物和饮料,但她不知道可以最多喂饱多少牛,(喂饱当然是有吃有喝才会饱) ...

  6. POJ 3281 网络流 拆点保证本身只匹配一对食物和饮料

    如何建图? 最开始的问题就是,怎么表示一只牛有了食物和饮料呢? 后来发现可以先将食物与牛匹配,牛再去和饮料匹配,实际上这就构成了三个层次. 起点到食物层边的容量是1,食物层到奶牛层容量是1,奶牛层到饮 ...

  7. POJ 3281 Dining(最大流+拆点)

    题目链接:http://poj.org/problem?id=3281 题目大意:农夫为他的 N (1 ≤ N ≤ 100) 牛准备了 F (1 ≤ F ≤ 100)种食物和 D (1 ≤ D ≤ 1 ...

  8. 图论--网络流--最大流--POJ 3281 Dining (超级源汇+限流建图+拆点建图)

    Description Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, an ...

  9. POJ 3281 Dining(网络流拆点)

    [题目链接] http://poj.org/problem?id=3281 [题目大意] 给出一些食物,一些饮料,每头牛只喜欢一些种类的食物和饮料, 但是每头牛最多只能得到一种饮料和食物,问可以最多满 ...

随机推荐

  1. nginx Keepalived高可用集群

    一.Keepalived高可用 1.简介 Keepalived软件起初是专为LvS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP功能.因此, ...

  2. atm-interface-shopping

    from db import db_handlerfrom interface import bank def shopping_interface(name, cost, shoppingcart) ...

  3. php 获取 今天、昨天、这周、上周、这月、上月、近30天

    <?php //今天 $today = date("Y-m-d"); //昨天 $yesterday = date("Y-m-d", strtotime( ...

  4. php 多维数组指定某个值作为键

    $temp_key = array_column($mobile_arr,'cidf'); //键值 $mobile_arr = array_combine($temp_key,$mobile_arr ...

  5. 动态规划:最长上升子序列之基础(经典算法 n^2)

    解题心得: 1.注意动态转移方程式,d[j]+1>d[i]>?d[i]=d[j]+1:d[i] 2.动态规划的基本思想:将大的问题化为小的,再逐步扩大得到答案,但是小问题的基本性质要和大的 ...

  6. L1-043 阅览室 (20 分)

    天梯图书阅览室请你编写一个简单的图书借阅统计程序.当读者借书时,管理员输入书号并按下S键,程序开始计时:当读者还书时,管理员输入书号并按下E键,程序结束计时.书号为不超过1000的正整数.当管理员将0 ...

  7. android/libs/libammsdk.jar" already exists! 解决方法

    Error: Uh oh!"/work/2016/fengkongbao/.meteor/local/cordova-build/platforms/android/libs/libamms ...

  8. Go语言之反射(二)

    反射的值对象 反射不仅可以获取值的类型信息,还可以动态地获取或者设置变量的值.Go语言中使用reflect.Value获取和设置变量的值. 使用反射值对象包装任意值 Go语言中,使用reflect.V ...

  9. C#入门篇6-4:字符串操作 string分割字符串效率比较

    //分割字符串效率比较 public static void Fund() { //1.用string.Split方法 //a.字节数组: //625毫秒/百万次 string str1 = &quo ...

  10. python小脚本(18-11.10)-修改excle后批量生成,作用:导入数据时,系统做了不能导入重复数据时的限制时使用 -本来是小白,大神勿扰

    from testcase.test_mokuai.operation_excle import OperationExcleimport shutil class test_daoru(): #一个 ...