<题目链接>

题目大意:

有N头牛,F种食物,D种饮料,每一头牛都有自己喜欢的食物和饮料,且每一种食物和饮料都只有一份,让你分配这些食物和饮料,问最多能使多少头牛同时获得自己喜欢的食物和饮料。

解题分析:

开始还以为是一道匹配问题,后面才知道这是用网络流求解。

首先我们要明确,如果按照源点——>食物——>牛——>饮料——>汇点这样建图,是不符合题目条件的。因为题目要求每头牛只能吃一份食物和饮料,而这样建图,如果一头牛对应多个食物和饮料,那这样那头牛是可以吃多份食物和饮料的,所以我们需要对牛进行拆点,并且拆除的两点之间用容量为1边相连,这样跑最大流的时候就能够限制每头牛最多只能吃一份食物和饮料了。下面是Dinic的模板。

 #include <cstdio>
 #include <cstring>
 #include <queue>
 #include <algorithm>
 using namespace std;

 #define INF 0x3f3f3f3f
 ;
 const int maxm = 1e5; 

 int depth[maxn], vis[maxn],cur[maxn], head[maxn];
 int N, F, D;
 int sect,cnt;    //sect为汇点
 struct Edge {
     int v, cap, flow, next;
 }edge[maxm];

 void init(){
     cnt = ;
     memset(head, -, sizeof(head));
 }

 void add(int u, int v, int w){
     edge[cnt].v = v, edge[cnt].cap = w, edge[cnt].flow = ,edge[cnt].next = head[u]; //正向弧(容量为w)
     head[u] = cnt++;
     edge[cnt].v = u, edge[cnt].cap = , edge[cnt].flow = ,edge[cnt].next = head[v]; //反向弧(容量为0)
     head[v] = cnt++;
 }

 void getmap(){
     int tmp1, tmp2;
     ; i <= N; ++i){
         scanf("%d%d", &tmp1, &tmp2);
         while(tmp1--){
             int num;
             scanf("%d", &num);
             add( * N + num, i, );//食物和左牛连接
         }
         while(tmp2--){
             int num;
             scanf("%d", &num);
             add(N + i,  * N + F + num, );//右牛和饮料连接
         }
         add(i, i + N, );//左牛和右牛连接
     }
     sect =  * N + F + D + ;
     ; i <= F; ++i)
         add(,  * N + i, );//源点和食物连接
     ; i <= D; ++i)
         add( * N + F + i,  * N + F + D + , );//饮料和超级汇点连接
 }

 bool BFS(int st, int ed){    //构建分层图,并且判断增广路径是否存在
     queue<int>q;
     memset(depth, -, sizeof(depth));    //将所有点分层,初始化深度为-1
     memset(vis,  ,sizeof(vis));
     q.push(st);
     depth[st] = ;   //源点深度为0
     vis[st] = ;
     while(!q.empty()){
         int u = q.front();
         q.pop();
         ; i = edge[i].next){
             Edge &E = edge[i];
             if(!vis[E.v] && E.cap > E.flow){
                 vis[E.v] = ;
                 depth[E.v] = depth[u] + ;    //下一个点是当前点的深度+1
                 if(E.v == ed) return true;    //找到汇点则直接返回
                 q.push(E.v);
             }
         }
     }
     return false;    //没有找到通向汇点的增广路径
 }

 int DFS(int x, int ed, int val){
     )
         return val;
     , f;
     ; i = edge[i].next){  //注意这里的&符号,这样i增加的同时也能改变cur[u]的值,达到更新当前弧的目的
         Edge E=edge[i];
          && (f = DFS(E.v, ed, min(val, E.cap - E.flow))) > ){  //f为残余网络中增广路径的最小残量
             edge[i].flow += f;    //进行增广
             edge[i ^ ].flow -= f;   //正向流量+f,相当于反向流量-f
             flow += f;
             val -= f;
             ) break;
         }
     }
     return flow;
 }

 int Dinic(int st, int ed){
     ;  //最大流
     while(BFS(st, ed)){     //判断是否存在增广路
         memcpy(cur, head, sizeof(head));    //当前弧优化
         sumflow += DFS(st, ed, INF);
     }
     return sumflow;
 }

 int main (){
     while(scanf("%d%d%d", &N, &F, &D) != EOF){
         init();
         getmap();    //建图
         printf(, sect));
     }
     ;
 }

2018-11-23

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. python之通过thread来实现多进程

    代码如下: import threading, time class Test1(threading.Thread): def __init__(self, name): super().__init ...

  2. PHP中json_encode()使用须知,JSON数组和JSON对象

    ⊰ 偷偷的告诉你,这是一个很不谨慎就会踩得坑 ⊱  如下代码 (看了一下很简单,没毛病啊,老铁) $arr = array( '0'=>'a','1'=>'b','2'=>'c',' ...

  3. 分布式通讯架构RPC简单实现

    什么是RPC: RPC(Remote Procedure Call,远程过程调用),一般用来实现部署在不同机器上的系统之间的方法调用,使得程序能够像访问本地系统资源一样,通过网络传输去访问远端系统资源 ...

  4. LeetCode(96): 不同的二叉搜索树

    Medium! 题目描述: 给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: ...

  5. ajax执行成功后,在success回调函数中把后台返回的list还原到html的table中

    需求描述:前台通过onclick触发ajax,到后台返回一个list(json格式的),把list插入到html的table中. 思路简介: ̄□ ̄|| 刚开始的时候,是没有思路的,就卡在了,怎么把 a ...

  6. IP的计算

    IP的计算 时间限制: 1 Sec  内存限制: 32 MB 位无符号整数来表示,一般用点分方式来显示,点将IP地址分成4个部分,每个部分为8位,表示成一个无符号整数(因此不需要用正号出现),如192 ...

  7. Allegro PCB Design GXL (legacy) 使用slide推挤走线,走线的宽度就发生改变的原因

    Allegro PCB Design GXL (legacy) version 16.6-2015 使用slide推挤走线,走线的宽度就会发生改变. 后来发现是因为约束管理器(Constraint M ...

  8. C++ friend友元函数和友元类(转)

    一个类中可以有 public.protected.private 三种属性的成员,通过对象可以访问 public 成员,只有本类中的函数可以访问本类的 private 成员.现在,我们来介绍一种例外情 ...

  9. 俺也会刷机啦--windows7下刷android

    刷机很多人都会,本文只为像我这种入门的朋友而写的. 风险提示: 1. SD卡数据极可能会丢失(我这次就全丢了). 2. 升级失败. (俺的)环境说明: windows7 专业版64位 cmd命令行工具 ...

  10. 步步为营-87-imageAreaSelect插件使用(图片剪切)

    1 引用文件 jquery.imgareaselect.min.cs imgareaselect-default.js 2 代码 <%@ Page Language="C#" ...