(点击此处查看原题)

题目分析

题意:某个餐馆出售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. webpack官方文档分析(一):安装

    一:安装 1.首先要安装Node.js->node.js下载 2.本地安装 要安装最新版本或特定版本,运行如下: npm install --save-dev webpack npm insta ...

  2. Codeforces 474D Flowers(DP)

    题目链接 非常简单的一道dp题,通过O(n)的预处理来使查询变为O(1). 主要的坑在于取模后的dp数组的前缀和再相减可能得到负数,导致无法得到某一区间和的取模. 解决方法:(a-b)%mo==(a% ...

  3. centos 链接错误解决方法

    执行除cd sln以外任何指令都报错,解决方法:sln /usr/lib64/ld-2.17.so /usr/lib64/ld-linux-x86-64.so.2 LD_PRELOAD=/lib64/ ...

  4. 批量插入数据@Insert

    // 批量插入数据 @Insert("<script>" + "insert into index_kline (currency_id, currency, ...

  5. Nginx常见配置

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  6. 基本CSS布局二

    基本CSS布局二------基本页面布局二 /*主面板样式*/ #container { width:100%; margin:0px auto;/*主面板DIV居中*/ } /*顶部面板样式*/ # ...

  7. java tfserving grpc 通信调用代码解析 【重点参考】

    https://blog.csdn.net/shin627077/article/details/78592729/   [重点参考]

  8. 数据库开源框架之ormlite

    主页: http://ormlite.com/ 配置: 添加以下依赖 * compile 'com.j256.ormlite:ormlite-android:4.48' * compile 'com. ...

  9. Collapse 折叠面板

    通过折叠面板收纳内容区域 基础用法 可同时展开多个面板,面板之间不影响 <el-collapse v-model="activeNames" @change="ha ...

  10. __linux__、__POSIX__宏

    __linux__用于定义linux,__POSIX__不太了解,各系统的宏有如下: std::string getOsName() { #ifdef _WIN32 return "Wind ...