(点击此处查看原题)

题目分析

题意:某个餐馆出售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. Plx9030通讯卡驱动开发与接口封装

    在学校的时候,曾经采用DDK+Driverstudio+VC6.0环境做过9054视频采集卡的驱动开发,回想起调试过程,记得最清楚的就是过无数次的计算机蓝屏重启....今天第一天来到新公司,老大就说你 ...

  2. js 获取地址栏信息,可以传递多个参数

    //获取多个地址栏信息,name为地址栏参数名,可以传递多个参数 // 形式为 .html?id=12&a=2 function getQueryString(name){ var reg = ...

  3. HDU 5115 Dire Wolf ——(区间DP)

    比赛的时候以为很难,其实就是一个区间DP= =..思路见:点我. 区间DP一定要记住先枚举区间长度啊= =~!因为区间dp都是由短的区间更新长的区间的,所以先把短的区间更新完.. 代码如下: #inc ...

  4. Spring核心内容-认识bean

  5. spark streaming 4: DStreamGraph JobScheduler

    DStreamGraph有点像简洁版的DAG scheduler,负责根据某个时间间隔生成一序列JobSet,以及按照依赖关系序列化.这个类的inputStream和outputStream是最重要的 ...

  6. 设计模式--观察者模式--python

    观察者模式: 对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新. 主要解决: 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面.将这二者封装在 ...

  7. LC 877. Stone Game

    Alex and Lee play a game with piles of stones.  There are an even number of piles arranged in a row, ...

  8. LC 358. Rearrange String k Distance Apart

    Given a non-empty string s and an integer k, rearrange the string such that the same characters are ...

  9. 【React自制全家桶】四、React中state与props的分析与比较

    一.state 1.state的作用 state是React中组件的一个对象.React把用户界面当做是状态机,想象它有不同的状态然后渲染这些状态,可以轻松让用户界面与数据保持一致. React中,更 ...

  10. react-native命令初始化项目后可借助webstrom快速运行与调试项目

    利用webstorm工具打开RN项目,点击 然后添加 然后进行配置 最后,点击apply ,OK完成 后期运行项目直接点击: