(点击此处查看原题)

题目分析

题意:某个餐馆出售f种食物,d种饮料,其中,第i种食物有fi份,第i种饮料有di份;此时有n个人来餐馆吃饭,这n个人必须有一份食物和一份饮料才会留下来吃饭,否则,他将离去,而且每个人只吃某几种食物和饮料,如果某个人留下来,那么必须提供一份他吃的食物和一份他吃饮料,问在这种情况下,最多可以招待多少人。

思路:这类的题目我总结为:最大流受到两个互不影响的物体的影响,这类题目为最大流题目,建边如下:

1)由源点向每一种食物i代表的结点建一条容量为fi的边

2)将每个顾客代表的结点拆成左结点和右结点,由左结点向右结点建一条容量为1的边

3)由每一种食物i代表的结点向对应顾客的左端点建一条容量为1的边(代表某一顾客可以食用这一食物)

4)由每个顾客的右端点向其可食用的饮料代表的结点i建一条容量为1的边

5)由每个饮料代表的结点i向汇点建一条容量为di的边

最后,跑出来的最大流即为答案。

(这个题的数据其实还是比较大的,边的总数超过1e5,注意一下就好)

代码区

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip> #define bug cout << "**********" << endl
#define show(x, y) cout<<"["<<x<<","<<y<<"] "
#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = ;
const int Max = 1e5 + ;
const int Max2 = 1e3 + ; struct Edge
{
int to, next, flow;
} edge[Max<<]; int n, f, d, s, t;
int head[Max], tot;
int dis[Max]; void init()
{
memset(head, -, sizeof(head));
tot = ;
s = ;
t = f + d + * n + ;
} void add(int u, int v, int flow)
{
edge[tot].to = v;
edge[tot].flow = flow;
edge[tot].next = head[u];
head[u] = tot++;
} bool bfs() //判断连通性,将图分层次
{
queue<int>q;
memset(dis, -, sizeof(dis));
dis[s] = ;
q.push(s); //源点
while (!q.empty())
{
int u = q.front();q.pop(); for (int i = head[u]; i != -; i = edge[i].next)
{
int v = edge[i].to;
if (dis[v] == - && edge[i].flow > )
{
dis[v] = dis[u] + ;
q.push(v);
if (v == t) return true;
}
}
}
return false;
} int dfs(int u, int flow_in)
{
if (u == t) return flow_in;
int flow_out = ; //实际流出流量
for (int i = head[u];i != -;i = edge[i].next)
{
int v = edge[i].to;
if (dis[v] == dis[u] + && edge[i].flow > )
{
int flow_part = dfs(v, min(flow_in, edge[i].flow));
if (flow_part == )continue; //无法形成增广路
flow_in -= flow_part;
flow_out += flow_part;
edge[i].flow -= flow_part;
edge[i ^ ].flow += flow_part;
if (flow_in == )break;
}
}
return flow_out;
} int Dinic()
{
int sum = ;
while (bfs())
{
sum += dfs(s, inf);
}
return sum;
} int main()
{
#ifdef LOCAL
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endif
while (scanf("%d%d%d", &n, &f, &d) != EOF)
{
init(); //s:0 ; f: 1~F ; man: F+1~F+2*n ; d: F+2*n+1~F+2*n+D ; t: F+2*n+D+1
for (int i = , flow; i <= f; i++)
{
scanf("%d", &flow);
add(s, i, flow);
add(i, s, ); //由源点向F建边权为fi的边
}
for (int i = f + * n + , flow; i <= f + * n + d; i++)
{
scanf("%d", &flow);
add(i, t, flow);
add(t, i, ); //由D向汇点建边权为di的边
}
for (int i = f + ; i <= f + n; i ++)
{
add(i, i + n, );
add(i + n, i, ); //拆点
char str[];
scanf("%s", str);
for (int j = ; j <= f; j++)
{
if (str[j - ] == 'Y')
{
add(j, i, );
add(i, j, ); //由F向顾客建一条容量为1的边
}
}
}
for (int i = f + ; i <= f + n; i++)
{
char str[];
scanf("%s",str);
for(int j = f + * n + ; j <= f + * n + d; j ++)
{
if(str[j-f-*n-] == 'Y')
{
add(i+n, j, );
add(j, i+n, ); //由顾客向D建一条容量为1的边
}
}
}
printf("%d\n",Dinic());
}
return ;
}

扩展

这个题目的类型为:最大流受到两个互不影响的物体的影响,然后,我想着,如果物体的个数为3个或者3个以上,那么该如何建图呢?比如说下面这个题目:

有一个餐馆,有A种饭,B种菜,C种汤,其中第i种饭有ai份(1<=i<=A),第i种菜有bi份(1<=i<=B),第i种汤有ci份(1<=i<=C)

此时有n个人进入餐馆用餐,已知每个人必须选择1份饭,1份菜和1份汤,

而且第i个人只吃qi种饭,分别为x1,x2….xq1,同时也只吃wi种菜,分别为y1,y2…yw1,只吃ei种汤,分别为z1,z2…zei

如果某个人无法得到他需要的一饭一菜一汤,他将离去。不会付款,也不会消耗任何事物。如果某个人如果得到了他所需的所有食物,他将给与你vali元饭钱

问如何招待顾客,可以让你得到最多的钱

自己思考后,又请教了几位大佬,最后的结论是:这个题无法求解...,至少缺乏高效的方法,如果有知道解法的大佬,请指教

HDU 4292 Food (建图思维 + 最大流)的更多相关文章

  1. POJ - 1149 PIGS (建图思维+最大流)

    (点击查看原题) 题目分析 (以下均为 Edelweiss 大佬的思路,博主承认自己写不了这么好,但是学习的心促使我记录下这个好题的写法,所以代码是我写的) [题目大意] 有 M 个猪圈,每个猪圈里初 ...

  2. HDU 4292 Food (网络流,最大流)

    HDU 4292 Food (网络流,最大流) Description You, a part-time dining service worker in your college's dining ...

  3. POJ 1149 PIGS 建图,最大流

    题意: 你m个猪圈以及每个猪圈里原来有多少头猪,先后给你n个人,每个人能打开某一些猪圈并且他们最多想买Ki头猪,在每一个人买完后能将打开的猪圈中的猪顺意分配在这次打开猪圈里,在下一个人来之前 已打开的 ...

  4. hdu4560 不错的建图,二分最大流

    题意: 我是歌手 Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Subm ...

  5. hdu 4857 逆向建图+拓扑排序 ***

    题意:糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行.现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前.同时,社会是不平等的,这些人有的穷有 ...

  6. ZOJ 1654 Place the Robots建图思维(分块思想)+二分匹配

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=654 AC一百道水题,不如AC一道难题来的舒服. 题意:一个n*m地图 ...

  7. HDU 4522 (恶心建图)

    湫湫系列故事——过年回家 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total ...

  8. 牛客练习赛53 D 德育分博弈政治课 (思维建图,最大流)

    牛客练习赛53 D德育分博弈政治课 链接:https://ac.nowcoder.com/acm/contest/1114/D来源:牛客网 题目描述 德育分学长最近玩起了骰子.他玩的骰子不同,他的骰子 ...

  9. Leapin' Lizards(经典建图,最大流)

    Leapin' Lizards http://acm.hdu.edu.cn/showproblem.php?pid=2732 Time Limit: 2000/1000 MS (Java/Others ...

随机推荐

  1. canvas小实验

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 数据分析-excel数据分析(数据分析师岗位分析)

    使用的函数:字符截取函数:LEFT(),MID()  定位函数:FIND()   统计函数:COUNTIF() 1.获取薪资的区间的最小值min和最大值max 处理方法:新插入多列,使用find()定 ...

  3. 统计mysql某个数据库的表数量以及表记录数

        统计MySQL中某个数据库中有多少张表 SELECT count(*) TABLES, table_schema FROM information_schema.TABLES    where ...

  4. JSON 转含有泛型属性的对象

    在将 json 字符串转为对象时,如果对象含有泛型,在进行转换时需要指明泛型类型. 1. 对象只含有一个泛型属性时 1.1  代码 /** * @Describe: * @Author: chenfa ...

  5. centos6.5和centos7如何搭建php环境(包括php7)

    查看下centos的版本信息: #适用于所有的linux lsb_release -a #或者 cat /etc/redhat-release #又或者 rpm -q centos-release 安 ...

  6. 【软件工程】团队Git现场编程实战

    组长博客链接 博客链接 组员职责分工 队员 职责分工 恩泽 进行任务的划分与安排,调用API,负责餐饮商铺及商圈信息的获取 金海 解析API返回的json数据,提取有关信息 君曦 部分算法编写 季城 ...

  7. LeetCode 88. 合并两个有序数组(Merge Sorted Array)

    题目描述 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明: 初始化 nums1 和 nums2 的元素数量分别为 m ...

  8. python pandas(ix & iloc &loc)

    python pandas(ix & iloc &loc) loc——通过行标签索引行数据 iloc——通过行号索引行数据 ix——通过行标签或者行号索引行数据(基于loc和iloc ...

  9. [转]springboot启动原理

    参考文章:https://www.jianshu.com/p/ef6f0c0de38f

  10. 计算机组成原理 — CPU 中央处理器

    目录 文章目录 目录 前文列表 逻辑电路部件 组合逻辑电路 时序逻辑电路 阵列逻辑电路 中央处理器(CPU) 控制单元(控制器) 运算单元(运算器) 存储单元(寄存器组和片内缓存) CPU 的工作原理 ...