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 ...
随机推荐
- 大话数据结构pdf高清版下载
大话数据结构PDF下载 不得不说严老师版的虽然比较经典,但是真的有点难理解啊,而大话数据结构这本书还是比较不错的,通俗易懂,反正我个人觉得很不错,希望对诸位有帮助. 链接:点击打开 密码:xovz p ...
- shell脚本中source无效
发现在shell里面执行source,提示找不到命令.所以,我取搜了一些资料,总结一下. 一. 脚本中,source找不到命令--------------是因为用了sh执行脚本,而debian系统的s ...
- 不用form怎么post数据
数据传输是用户交互中最重要的环节,下面收集了几个数据传输的方法,作为记录(未测试,在使用之前需要测试,如果后面我测试了,会对已测试项进行标注) 一. 网址传递 <a href=”test.php ...
- Git 基础教程 之 删除文件
① 手动或命令 rm删除工作区的问价: git checkout -- readme.txt 可恢复 checkout 实际上是用版本库里的替换工作区的版本 ② 删除了工作区文 ...
- EditorLineEnds.ttr的困扰
DELL的n年的商用机电脑硬盘坏了,措手不及. 256ssd+1tb企业级.机器快乐很多.一小步,让机器快了一大步. 但是2007出问题了,每次启动EditorLineEnds.ttr被占用.原来有那 ...
- 【[Offer收割]编程练习赛15 B】分数调查
[题目链接]:http://hihocoder.com/problemset/problem/1515 [题意] [题解] 带权并查集 relation[x]表示父亲节点比当前节点大多少; 对于输入的 ...
- MySQL主要命令(4)
显示数据, 给列区别名: select coL_name as 别名 from table_name;
- navicat 为表添加索引
navicat 为表添加索引 分析常用的查询场景,为字段添加索引,增加查询速度. 可以添加单列索引,可以添加联合索引. 右键,设计表中可以查看和添加修改索引! 索引一定要根据常用的查询场景进行添加! ...
- 并查集图冲突hdu1272
还是属于并查集的变形 两个点仅仅有一条路径连通 给出的两个点事先都是属于两个集合的 须要给出的着条边构成一个集合 算法复杂度还是挺高的 每一个我都循环了100000次 set2数组没清空 wrong了 ...
- java.lang.NoClassDefFoundError: org/json/JSONException
问题: 解决办法: