题意 : 有 N 头牛,John 可以制作 F 种食物和 D 种饮料, 然后接下来有 N 行,每行代表一头牛的喜好==>开头两个数 F和 D表示这头牛喜欢 F种食物, Di  种饮料,接下来 F个数表示喜欢的食物编号,Di  个数表示喜欢的饮料的编号,现在 John 要使用最优决策制作出 F 种食物和 D 种饮料,问怎么喂才能使尽可能多的牛喂饱 ( 喂饱 = 一份食物一份饮料,且一头牛最多消耗一份食物和一份饮料 ),最后输出最多喂饱的牛数。

分析:如果是只有食物或者饮料一种的话,很容易就可以想到用二分图算法来解决,可是现在题目有了两个限制的条件,食物与饮料一起满足。首先想到的是 牛=》食物=》饮料,可是这样的话,并没有唯一性,牛可以被分配到多组饮料和食物。这是不行的我们转化下,如果是食物=》牛=》饮料,这样也是不行的,但是我们在把牛在拆分成两个点,食物=》牛=》牛=》饮料,那这样就可以满足唯一性了;真的是NB来的。

#include<stdio.h>
#include<queue>
#include<vector>
#include<string.h>
using namespace std;
const int maxn = +;
#define INF 0x3f3f3f3f
int N,F,D;
struct Edge
{
int from,to,cap,flow;
Edge(){}
Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow){}
}; struct Dinic
{
int n,m,s,t; //结点数,边数(包括反向弧),源点与汇点编号
vector<Edge> edges; //边表 edges[e]和edges[e^1]互为反向弧
vector<int> G[maxn]; //邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
bool vis[maxn]; //BFS使用,标记一个节点是否被遍历过
int d[maxn]; //d[i]表从起点s到i点的距离(层次)
int cur[maxn]; //cur[i]表当前正访问i节点的第cur[i]条弧 void init(int n,int s,int t)
{
this->n=n,this->s=s,this->t=t;
for(int i=;i<=n;i++) G[i].clear();
edges.clear();
} void AddEdge(int from,int to,int cap)
{
edges.push_back( Edge(from,to,cap,) );
edges.push_back( Edge(to,from,,) );
m = edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} bool BFS()
{
memset(vis,,sizeof(vis));
queue<int> Q;//用来保存节点编号的
Q.push(s);
d[s]=;
vis[s]=true;
while(!Q.empty())
{
int x=Q.front(); Q.pop();
for(int i=; i<G[x].size(); i++)
{
Edge& e=edges[G[x][i]];
if(!vis[e.to] && e.cap>e.flow)
{
vis[e.to]=true;
d[e.to] = d[x]+;
Q.push(e.to);
}
}
}
return vis[t];
} //a表示从s到x目前为止所有弧的最小残量
//flow表示从x到t的最小残量
int DFS(int x,int a)
{
if(x==t || a==)return a;
int flow=,f;//flow用来记录从x到t的最小残量
for(int& i=cur[x]; i<G[x].size(); i++)///注意这里的&符号,这样i增加的同时也能改变cur[u]的值,达到记录当前弧的目的
{ Edge& e=edges[G[x][i]];
if(d[x]+==d[e.to] && (f=DFS( e.to,min(a,e.cap-e.flow) ) )> )
{
e.flow +=f;
edges[G[x][i]^].flow -=f;
flow += f;
a -= f;
if(a==) break;
}
}
if(!flow) d[x] = -;///炸点优化
return flow;
} int Maxflow()
{
int flow=;
while(BFS())
{
memset(cur,,sizeof(cur));
flow += DFS(s,INF);
}
return flow;
}
}DC;
///0-n-1 ; 食物的牛
///n-2n-1:饮料的牛
///2n-2n+f-1:食物
///2n+f-2n+d-1:饮料
int main( )
{
int x,q,w;
while(scanf("%d%d%d",&N,&F,&D)!=EOF)
{
int s = ,t=+*N+F+D;
DC.init(t+,s,t);
for(int i= ; i<=N ; i++)
{
scanf("%d",&q);scanf("%d",&w);
while(q--)
{
scanf("%d",&x);
DC.AddEdge(*N+x,i,);//食物到牛
} while(w--)
{
scanf("%d",&x);
DC.AddEdge(N+i,*N+x+F,);//牛到饮料
}
DC.AddEdge(i,N+i,);//牛到牛
} for(int i= ; i<=F ; i++)
{
DC.AddEdge(s,*N+i,);
}
for(int i= ; i<=D ; i++)
{
DC.AddEdge(*N+i+F,t,);
}
printf("%d\n",DC.Maxflow()); }
return ;
}

POJ 3281 Dining ( 最大流 && 建图 )的更多相关文章

  1. POJ 3281 Dining(最大流)

    POJ 3281 Dining id=3281" target="_blank" style="">题目链接 题意:n个牛.每一个牛有一些喜欢的 ...

  2. POJ 3281 Dining(最大流板子)

    牛是很挑食的.每头牛都偏爱特定的食物和饮料,其他的就不吃了. 农夫约翰为他的牛做了美味的饭菜,但他忘了根据它们的喜好检查菜单.虽然他不可能喂饱所有的人,但他想让尽可能多的奶牛吃上一顿有食物和水的大餐. ...

  3. POJ 3281 Dining(最大流+拆点)

    题目链接:http://poj.org/problem?id=3281 题目大意:农夫为他的 N (1 ≤ N ≤ 100) 牛准备了 F (1 ≤ F ≤ 100)种食物和 D (1 ≤ D ≤ 1 ...

  4. 【网络流#7】POJ 3281 Dining 最大流 - 《挑战程序设计竞赛》例题

    不使用二分图匹配,使用最大流即可,设源点S与汇点T,S->食物->牛->牛->饮料->T,每条边流量为1,因为流过牛的最大流量是1,所以将牛拆成两个点. 前向星,Dini ...

  5. POJ 3281 Dining 最大流

    饮料->牛->食物. 牛拆成两点. //#pragma comment(linker, "/STACK:1024000000,1024000000") #include ...

  6. 图论--网络流--最大流--POJ 3281 Dining (超级源汇+限流建图+拆点建图)

    Description Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, an ...

  7. poj 3281 最大流+建图

    很巧妙的思想 转自:http://www.cnblogs.com/kuangbin/archive/2012/08/21/2649850.html 本题能够想到用最大流做,那真的是太绝了.建模的方法很 ...

  8. POJ 3281 Dining (网络流)

    POJ 3281 Dining (网络流) Description Cows are such finicky eaters. Each cow has a preference for certai ...

  9. poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙

    /** 题目:poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙 链接:http://poj.org/problem?id=3680 题意:给定n个区间,每个区间(ai,bi ...

随机推荐

  1. Spring注解-TaskScheduler

    一.定义配置类 import org.springframework.context.annotation.ComponentScan; import org.springframework.cont ...

  2. Xcode快捷

  3. 201671010127 2016—2017—2 Java学习周结

    时间真是个最公平东西,只要能够好好地利用它,它可以为我们带来我们我们所想要的东西.学习Java已经有一周了,对于Java基础知识的认识也更进一步,对Java的兴趣也愈来愈浓.实现一个Java程序,主要 ...

  4. oracle --(二)分区(extent)

    基本关系:数据库---表空间---数据段---分区---数据块 一.分区(extent)分区extent是比数据块大一级的存储结构,是几个逻辑上相邻的data block的组合.我们知道,物理存储通常 ...

  5. [poj1410]Intersection

    题目大意:求线段与实心矩形是否相交. 解题关键:转化为线段与线段相交的判断. #include<cstdio> #include<cstring> #include<al ...

  6. Angular问题03 @angular/material版本问题

    1 问题描述 应用使用 angular4在使用@angular/material时,若果在导入模块时使用mat开头,就会报错. 2 问题原因 @angular/material版本出现问题,@angu ...

  7. ruby 【rails在win7_64位操作系统安装】

    gem update --system --source http://production.s3.rubygems.org 安装截图

  8. tar打包tar.gz文件

    命令格式: tar zcvf dir.tar.gz ./dir 压缩后的文件解压出来会是dir这个文件夹

  9. Win32编程中如何处理控制台消息

    这篇文章讨论如何处理所有的控制台消息. 第一步,首先要安装一个事件钩子,也就是说要建立一个回调函数.调用Win32 API,原型如下: BOOL SetConsoleCtrlHandler(PHAND ...

  10. 关于IO流---笔记1

    今日内容介绍1.File2.递归=================================================================================1 I ...