题目链接:点击查看

题目大意:给出n头奶牛,f种食物,d种饮料,每只奶牛可以选择数种食物和饮料,但每种食物和饮料只有一份,现在问最多能让多少头奶牛同时满足食物和饮料的条件

题目分析:最大流的题目,不过建图是真的神奇,一开始我是想将奶牛拆点,拆成饮料点和食物点,然后源点连到食物+饮料,奶牛点连到汇点,但食物饮料和奶牛之间不会建边,然后就卡住了

我们必须从题目入手,首先关键信息是:

  1. 每一头满足条件的奶牛一定同时匹配一个饮料+一个食物
  2. 每头奶牛最多只能匹配一个饮料+一个食物

这样一来,我们就能将问题转换一下,跳出思维定式,让奶牛与食物饮料的匹配,变为食物通过奶牛与饮料匹配(反之亦然),这样一想,我们只需要将奶牛拆点,中间建边,流量为1就好了,流量为1说明只允许一条路径通过,那么该条路径需要从食物引出,从饮料结束,完成上述两个条件的配对

建边方法:

  1. 源点->每个食物,流量为1
  2. 每个食物->可选择的奶牛的入点,流量为1
  3. 每头奶牛的入点->每头奶牛的出点,流量为1
  4. 每头奶牛的出点->可选择的饮料,流量为1
  5. 每个饮料->汇点,流量为1

这样建完图后直接跑一遍最大流就能出答案了

不得不赞叹网络流神奇的建边技巧

代码:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=410;struct Edge
{int to,w,next;
}edge[N*N];//边数int head[N],cnt;void addedge(int u,int v,int w)
{edge[cnt].to=v;edge[cnt].w=w;edge[cnt].next=head[u];head[u]=cnt++;edge[cnt].to=u;edge[cnt].w=0;//反向边边权设置为0edge[cnt].next=head[v];head[v]=cnt++;
}int d[N],now[N*N];//深度 当前弧优化bool bfs(int s,int t)//寻找增广路
{memset(d,0,sizeof(d));queue<int>q;q.push(s);now[s]=head[s];d[s]=1;while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;int w=edge[i].w;if(d[v])continue;if(!w)continue;d[v]=d[u]+1;now[v]=head[v];q.push(v);if(v==t)return true;}}return false;
}int dinic(int x,int t,int flow)//更新答案
{if(x==t)return flow;int rest=flow,i;for(i=now[x];i!=-1&&rest;i=edge[i].next){int v=edge[i].to;int w=edge[i].w;if(w&&d[v]==d[x]+1){int k=dinic(v,t,min(rest,w));if(!k)d[v]=0;edge[i].w-=k;edge[i^1].w+=k;rest-=k;}}now[x]=i;return flow-rest;
}void init()
{memset(head,-1,sizeof(head));cnt=0;
}int solve(int st,int ed)
{int ans=0,flow;while(bfs(st,ed))while(flow=dinic(st,ed,inf))ans+=flow;return ans;
}int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);int n,f,d;while(scanf("%d%d%d",&n,&f,&d)!=EOF){//1~n:奶牛1 n+1~2*n:奶牛2 2*n+1~2*n+f:food 2*n+f+1~2*n+f+d:drink init();int st=N-1,ed=st-1;for(int i=1;i<=f;i++)//st->foodaddedge(st,2*n+i,1);for(int i=1;i<=d;i++)//drink->edaddedge(2*n+f+i,ed,1);for(int i=1;i<=n;i++)//cow1->cow2addedge(i,i+n,1);for(int i=1;i<=n;i++){int ff,dd;scanf("%d%d",&ff,&dd);while(ff--)//food{int x;scanf("%d",&x);addedge(2*n+x,i,1);}while(dd--)//drink{int x;scanf("%d",&x);addedge(i+n,2*n+f+x,1);}}printf("%d\n",solve(st,ed));}return 0;
}

POJ - 3281 Dining(最大流+思维建边)相关推荐

  1. POJ.3281 dining 最大流+拆点

    POJ.3281 dining 最大流+拆点 思路清晰为啥一直WA呢 #include <iostream> #include <cstring> #include <v ...

  2. poj 3281 Dining 最大流

    题目链接 一开始的想法就是food-cow-water,但是wa了,看了别人的思路知道每一只牛牛用一条边隔开,然后就达到了限流的效果. 所以 食物-->牛牛---->牛牛---->w ...

  3. 解题报告:POJ 3281 Dining(最大流 / “三分图”建图)

    B.POJ 3281 DiningDiningDining(最大流/建图模板)[省选/NOI- ] 有 F 种食物和 D 种饮料,每种食物或饮料只能供一头牛享用,且每头牛只享用一 种食物和一种饮料.现 ...

  4. POJ 3281 -- Dining(最大流,拆点建图)

    题目链接 Description Cows are such finicky eaters. Each cow has a preference for certain foods and drink ...

  5. POJ - 3680 Intervals(最大费用最大流+思维建边)

    题目链接:点击查看 题目大意:给出n个开区间,每个开区间都有一个权值,要求在重叠次数不超过k次的情况下,选出权值和最大的数个区间 题目分析:和之前网络流24题里最大k可重区间集问题一模一样的模板,就不 ...

  6. POJ 3281 (最大流+匹配+拆点)

    题目链接:http://poj.org/problem?id=3281 题目大意:有一些牛,一堆食物,一堆饮料.一头牛要吃一份食物喝一份饮料才算满足,而且牛对某些食物和饮料才有好感,问最多有多少头牛是 ...

  7. 洛谷 - P3980 [NOI2008]志愿者招募(最小费用最大流+思维建边)

    题目链接:点击查看 题目大意:现在有n天需要志愿者,每一天需要招募的人数是Ai个人,现在有m类志愿者,每类志愿者可以在[l,r]天内被招募,需要花费的代价为Ci,现在需要安排一种招募方式,可以使得总花 ...

  8. 洛谷 - P1251 餐巾计划问题(最小费用最大流+思维建边)

    题目链接:点击查看 题目大意:给出n天每天所需要的新餐巾的数量,现在有多种方式可以获得新餐巾,问如何运营能使花费最少: 直接购买,花费为cost 将脏餐巾送到快洗部,需要洗t1天,花费为c1 将脏餐巾 ...

  9. 洛谷 - P3358 最长k可重区间集问题(最大费用最大流+思维建边)

    题目链接:点击查看 题目大意:给出n个开区间,现在要求从中选取一定数量的区间,需要满足: 对于任意点x,所选取的区间中包含点x的个数小于等于k 区间长度和最大 要求输出最长的区间长度和 题目分析:一开 ...

最新文章

  1. 猫猫学iOS 之第一次打开Xcode_git配置,git简单学习
  2. HDU4009(最小树形图)
  3. Linux预备知识(一):进程隔离
  4. Linux参数顺序,【每日一linux命令3】参数(或称选项)顺序
  5. 网易邮箱开通imap服务器,网易邮箱率先全面默认开通IMAP服务
  6. 如何用python批量处理图片大小_python批量修改图片大小的方法
  7. Mysql(10)——聚合函数的用法
  8. enum to IEnumerableT
  9. Vue 2.0 v-for 响应式key, index及item.id参数对v-bind:key值造成差异研究
  10. 作者:李涛(1975-),男,南京邮电大学计算机学院、软件学院院长,南京邮电大学大数据研究院院长。...
  11. RouterOS计划任务实例
  12. jquery操作滚动条滚动到指定位置
  13. python点击按钮弹出新窗口_PyQt5点击button如何弹出新窗口?
  14. MATLAB R2018a 安装教程
  15. 腾讯打免费牌争抢市场 马化腾表示QQ旋风免费
  16. sql server 本地复制订阅 实现数据库服务器 读写分离
  17. jmeter测试mysql数据库_【JMeter】JMeter完成一个MySql压力测试
  18. Ubuntu16.04安装百度网盘亲测可用
  19. 基于stm32单片机srf04超声波传感器测距Proteus仿真
  20. 静态代理和动态代理的区别和联系

热门文章

  1. java命令行选项6_6.jdk命令行工具
  2. java finereport_java报表FineReport_JS整理
  3. MySQL from后面的子查询使用
  4. 数据库存储数据的特点
  5. 生产者消费者的实际使用
  6. AQS.doReleaseShared
  7. ReactJS入门之组件
  8. 常用IOC注解按照作用分类
  9. Lambda表达式的无参数无返回值的练习
  10. Redisson框架快速入门