题目链接:

  http://poj.org/problem?id=3281

题目大意:

  有n头牛,f种食物,d种饮料,第i头牛喜欢fi种食物和di种饮料,每种食物或者饮料被一头牛选中后,就不能被其他的牛选了,问最多能满足多少头牛的要求?

解题思路:

  最大匹配问题,关键在于如何建图,可以虚构出来一个源点,一个汇点,一共需要f+d+2*n+2个点即可,建图为:源点—>食物—>牛—>牛—>饮料—> 汇点。把牛作为点拆开建图是为了让一头牛只对应一种饮料和一种食物,避免出现对应多种饮料或者多种食物的情况。

代码:

 #include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
using namespace std; #define maxn 0x3f3f3f3f
#define N 410
int map[N][N], Layer[N], s, e;
bool visit[N];
bool CountLayer();
int Dinic (); int main ()
{
int n, f, d, x, y, m;
while (scanf ("%d %d %d", &n, &f, &d) != EOF)
{
s = , e = f + d + n + n + ;
memset (map, , sizeof(map)); for (int i=; i<=f; i++)
map[][i] = ;//食物和源点连线 for (int i=; i<=d; i++)
map[i+f+*n][e] = ;//饮料和汇点链接 for (int i=; i<=n; i++)
map[i+f][i+f+n] = ;//对应的牛和牛链接 for (int i=; i<=n; i++)
{//建立牛和食物及饮料的关系
int num = f + i;
scanf ("%d %d", &x, &y);
while (x --)
{
scanf ("%d", &m);
map[m][num] = ;
}
while (y --)
{
scanf ("%d", &m);
map[num + n][m+f+*n] = ;
}
}
printf ("%d\n", Dinic());
}
return ;
} bool CountLayer()
{
deque <int> Q;
memset (Layer, , sizeof(Layer));
Layer[] = ;
Q.push_back();
while (!Q.empty())
{
int nd = Q.front();
Q.pop_front();
for (int i=s; i<=e; i++)
{
if (map[nd][i]> && !Layer[i])
{
Layer[i] = Layer[nd] + ;
if (i == e)
return true;
else
Q.push_back(i);
}
}
}
return false;
} int Dinic ()//Dinic模板
{
int maxnflow = , i;
while (CountLayer())
{
deque<int>Q;
memset (visit, , sizeof(visit));
visit[] = ;
Q.push_back();
while (!Q.empty())
{
int nd = Q.back();
if (nd != e)
{
for (i=; i<=e; i++)
{
if (map[nd][i]> && Layer[i] == Layer[nd]+ && !visit[i])
{
visit[i] = ;
Q.push_back(i);
break;
}
}
if (i > e)
Q.pop_back();
}
else
{
int minflow = maxn;
int mv;
for (i=; i<Q.size(); i++)
{
int ns = Q[i-];
int ne = Q[i];
if (map[ns][ne] < minflow)
{
minflow = map[ns][ne];
mv = ns;
}
}
maxnflow += minflow;
for (i=; i<Q.size(); i++)
{
int ns = Q[i-];
int ne = Q[i];
map[ns][ne] -= minflow;
map[ne][ns] += minflow;
}
while (!Q.empty() && Q.back() != mv)
Q.pop_back();
}
}
}
return maxnflow;
}

最新文章

  1. 【虚拟机】oracle Virtual Box4.2.6虚拟机正在运行的过程中删除了其上的一个备份,之后虚拟机就无法使用了
  2. Web Audio介绍
  3. MapKit/CoreLocation框架 总结
  4. [20160731]read a file and print it on the screen
  5. git_2-linux
  6. Git学习记录
  7. 【WCF】Silverlight+wcf+自定义用户名密码验证
  8. HDOJ 1028 Ignatius and the Princess III (母函数)
  9. CListCtrl使用方法汇总
  10. Spring Data MongoDB example with Spring MVC 3.2
  11. 转: fscanf()函数详解
  12. Android中动态更新TextView上的文字
  13. 绿色mysql启动脚本
  14. 无尽的循环ViewPager
  15. 使用JSR-303进行校验
  16. Yarn的Linking dependencies特别慢的优化方法
  17. Study 4 —— 表单标签
  18. 3.C#的访问权限修饰符
  19. c语言数据类型(二)
  20. [转]mysql组合索引与字段顺序

热门文章

  1. DELPHI最新的产品路线图
  2. Fortinet网络接入及安全方案配置步骤
  3. Angular2.x-服务
  4. javaEE之------ApectJ的切面技术===标签
  5. 【Mongodb教程 第九课 】MongoDB 删除文档
  6. C#构造方法(函数) C#方法重载 C#字段和属性 MUI实现上拉加载和下拉刷新 SVN常用功能介绍(二) SVN常用功能介绍(一) ASP.NET常用内置对象之——Server sql server——子查询 C#接口 字符串的本质 AJAX原生JavaScript写法
  7. Android使用adb获得activity堆栈信息
  8. I2C上拉电阻取值范围
  9. Android TabHost设置setCurrentTab(index),当index!=0时,默认加载第一个tab问题解决方法。
  10. iOS开发——高级篇——多线程GCD死锁