poj3281 Dining 最大流(奇妙的构图)
我是按照图论500题的文档来刷题的,看了这题怎么也不觉得这是最大流的题目。这应该是题目做得太少的缘故。
什么是最大流问题?最大流有什么特点?
最大流的特点我觉得有一下几点:
1、只有一个起点、一个终点。如果不是,我们可以构造超级源点,超级汇点。
2、边的容量有上限(有上下限的是另外一种特殊的最大流)。
3、最后求的是一个最大值。
这题可以找到一些影子,一头奶牛只能吃一种食物,喝一种饮料。如果只有一种限制我们能很快反应过来(二分最大匹配),但是两种限制就增加了难度。不过还是可以理解为对边的权值的限制,最后求最大值,就可以网最大流的方向去思考。
怎么建图成了解题的关键。怎么确定一头牛只吃一种食物,只喝一种饮料呢?一种食物被多头牛喜欢,一种饮料也被多头牛喜欢。比较如意理解的是多头牛想喝A饮料,就从这么多头牛(点)连边到A,然后A连一条边出去,边权是1,就决定了,A只能被一头牛选择。
具体的建图:
1、建立一个超级源点,向所有的食物(F个点)连权值都为1的边。超级源点假设是0。
2、从食物向牛连边,权值为1。食物被那头牛喜欢就连一条边。食物的编号为1~F。牛的编号是F+1 ~F+N。
3、牛向牛连边。可以理解为自己向自己连边,权值为1。但是编号不能相同。这就是拆点。这是很关键的一点。可以理解为有两个属性的一一对应,就是食物与饮料是一一对应的。前面的牛是F+1,与之对应的头的编号是F+1+N。
4、建立一个超级汇点,是所有的饮料都连向汇点。汇点编号为F+2*N+D+1。
我的代码在源点和汇点是有出入,源点S不是0,是F+2*N +D+1,汇点的 S+1。主要是SAP的模版习惯下标从1开始。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
const int M=*N*N, INF=0x3f3f3f3f;
struct node
{
int to,next,w;
}edge[M];
int head[N],numh[N],h[N],cure[N],pre[N];
int ans,tot;
void SAP(int s, int e,int n)
{
int flow,u,tmp,neck,i;
ans=;
for(i=;i<=n;i++)
cure[i]=head[i];
numh[]=n;
u=s;
while(h[s]<n)
{
if(u==e)
{
flow =INF;
for(i=s;i!=e;i=edge[cure[i]].to)
{
if(flow>edge[cure[i]].w)
{
neck=i;
flow =edge[cure[i]].w;
}
}
for(i=s;i!=e;i=edge[cure[i]].to)
{
tmp=cure[i];
edge[tmp].w-=flow;
edge[tmp^].w+=flow;
}
ans+=flow;
u=neck;
}
for(i=cure[u];i!=-;i=edge[i].next)
if(edge[i].w && h[u]==h[edge[i].to]+) break;
if(i!=-) {cure[u]=i;pre[edge[i].to]=u;u=edge[i].to;}
else
{
if(==--numh[h[u]]) break; //GAP优化
cure[u]=head[u];
for(tmp=n,i=head[u];i!=-;i=edge[i].next)
if(edge[i].w) tmp=min(tmp, h[edge[i].to]);
h[u]=tmp+;
++numh[h[u]];
if(u!=s) u=pre[u];
}
}
}
void init()
{
tot=;
memset(head,-,sizeof(head));
memset(pre,-,sizeof(pre));
memset(h,,sizeof(h));
memset(numh,,sizeof(numh)); }
void addedge(int i,int j,int w)
{
edge[tot].to=j;edge[tot].w=w;edge[tot].next=head[i];head[i]=tot++;
edge[tot].to=i;edge[tot].w=;edge[tot].next=head[j];head[j]=tot++;
}
int main()
{
//freopen("test.txt","r",stdin);
int n,m,i,j,k,a,b,c,s,d,f;
while(scanf("%d%d%d",&a,&b,&c)!=EOF)
{
init();
// 1~b是食物编号,b+1 ~b+2a是牛的编号,b+2a+1 ~ b+2a+c是饮料的编号
s=*a+b+c+; n=*a+b+c+;
for(i=;i<=b;i++) addedge(s,i,);
for(i=;i<=a;i++)
{
scanf("%d%d",&f,&d);
for(j=;j<f;j++)
{
scanf("%d",&k);
addedge(k,b+i,);
}
for(j=;j<d;j++)
{
scanf("%d",&k);
addedge(a+b+i,*a+b+k,);
}
}
for(i=b+;i<=b+a;i++) addedge(i,i+a,);
for(i=*a+b+;i<=*a+b+c;i++) addedge(i,n,);
SAP(s,n,n);
printf("%d\n",ans);
}
return ;
}
poj3281 Dining 最大流(奇妙的构图)的更多相关文章
- POJ3281 Dining —— 最大流 + 拆点
题目链接:https://vjudge.net/problem/POJ-3281 Dining Time Limit: 2000MS Memory Limit: 65536K Total Subm ...
- POJ3281 Dining 最大流
题意:有f种菜,d种饮品,每个牛有喜欢的一些菜和饮品,每种菜只能被选一次,饮品一样,问最多能使多少头牛享受自己喜欢的饮品和菜 分析:建边的时候,把牛拆成两个点,出和入 1,源点向每种菜流量为1 2,每 ...
- [poj3281]Dining(最大流+拆点)
题目大意:有$n$头牛,$f$种食物和$d$种饮料,每种食物或饮料只能供一头牛享用,且每头牛只享用一种食物和一种饮料.每头牛都有自己喜欢的食物种类列表和饮料种类列表,问最多能使几头牛同时享用到自己喜欢 ...
- POJ3281 Dining(拆点构图 + 最大流)
题目链接 题意:有F种食物,D种饮料N头奶牛,只能吃某种食物和饮料(而且只能吃特定的一份) 一种食物被一头牛吃了之后,其余牛就不能吃了第一行有N,F,D三个整数接着2-N+1行代表第i头牛,前面两个整 ...
- 2018.06.27 POJ3281 Dining(最大流)
Dining Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 21578 Accepted: 9545 Description C ...
- Dining(POJ-3281)【最大流】
题目链接:https://vjudge.net/problem/POJ-3281 题意:厨师做了F种菜各一份,D种饮料各一份,另有N头奶牛,每只奶牛只吃特定的菜和饮料,问该厨师最多能满足多少头奶牛? ...
- [Poj3281]Dining(最大流)
Description 有n头牛,f种食物,d种饮料,每头牛有nf种喜欢的食物,nd种喜欢的饮料,每种食物如果给一头牛吃了,那么另一个牛就不能吃这种食物了,饮料也同理,问最多有多少头牛可以吃到它喜欢的 ...
- poj3281 Dining
Dining Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 14316 Accepted: 6491 Descripti ...
- POJ3281(KB11-B 最大流)
Dining Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 19170 Accepted: 8554 Descripti ...
随机推荐
- Scala语言学习笔记——方法、函数及异常
1.Scala 方法及函数区别 ① Scala 有方法与函数,二者在语义上的区别很小.Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量.换句话来说在类中定义的函数即是方法 ② Scal ...
- 【ubuntu子系统】使用windows自带的ubuntu子系统
在windows10系统中,自带了一款ubuntu子系统,就像是一个应用程序,一款软件,提供ubutnu的terminal窗口,可以使用对应的命令行模式.最重要的是,可以直接用来连接linux服务 ...
- 【*2000】【2018-2019 ICPC, NEERC, Southern Subregional Contest C 】Cloud Computing
[链接] 我是链接,点我呀:) [题意] [题解] 我们可以很容易知道区间的每个位置有哪些安排可以用. 显然 我们优先用那些花费的钱比较少的租用cpu方案. 但一个方案可供租用的cpu有限. 我们可以 ...
- 防火墙对FTP的影响
http://www.5iadmin.com/post/919.html FTP 常用命令 http://www.cnblogs.com/emanlee/archive/2012/07/09/2583 ...
- [bzoj2131]免费的馅饼_树状数组
免费的馅饼 bzoj-2131 题目大意: 注释:$1\le n \le 10^5$,$1\le w \le 10^8$. 想法:首先,想到dp 状态:dp[i][j]表示i分钟在位置j的最大收益 优 ...
- libev与libuv的区别
参考: http://blog.csdn.net/w616589292/article/details/46475555 libuv 和 libev ,两个名字相当相近的 I/O Library,最近 ...
- POJ 1987
T_T为毛会这样子,我的写就是过不了,....... 其实这题不难,很容易想到吧,我一开始也想着用枚举这类方法,但复杂度实在不敢想,没想到,真的是用这种方法.. 今天学了一个叫树的重心,可以使分治的子 ...
- cefsharp 获取高度
G.browser.GetBrowser().MainFrame.ExecuteJavaScriptAsync("$(document).height()"); // Get Do ...
- DecimalFormat格式化输出带小数的数字类型
刚開始 double d = 333333333.333333333; System.out.println(d); 输出结果为3.333333333333333E8 网上找到了DecimalForm ...
- 网络:万维网(WWW)
ylbtech-网络:万维网(WWW) www (万维网缩写)同义词 万维网一般指www(万维网缩写)WWW是环球信息网的缩写,(亦作“Web”.“WWW”.“'W3'”,英文全称为“World Wi ...