题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4292

题意:水和饮料,建图跑最大流模板。

我用的是学长的模板,最然我还没有仔细理解,不过这都不重要直接贴就行了。

下面是AC代码,以后就当做最大流的模板来用了。

代码:

#include<cstdio>
#include<iostream>
using namespace std; const int oo=1e9;
const int mm=2e5+;
const int mn=1e5+; int node,src,dest,edge;
int ver[mm],flow[mm],Next[mm];
int head[mn],work[mn],dis[mn],q[mn]; int Min(int a,int b)
{
return a<b?a:b;
} void prepare(int _node,int _src,int _dest)
{
node=_node,src=_src,dest=_dest;
for(int i=; i<node; ++i)head[i]=-;
edge=;
} void Addedge(int u,int v,int c)
{
ver[edge]=v,flow[edge]=c,Next[edge]=head[u],head[u]=edge++;
ver[edge]=u,flow[edge]=,Next[edge]=head[v],head[v]=edge++;
} bool Dinic_bfs()
{
int i,u,v,l,r=;
for(i=; i<node; ++i)dis[i]=-;
dis[q[r++]=src]=;
for(l=; l<r; ++l)
for(i=head[u=q[l]]; i>=; i=Next[i])
if(flow[i]&&dis[v=ver[i]]<)
{
dis[q[r++]=v]=dis[u]+;
if(v==dest)return ;
}
return ;
} int Dinic_dfs(int u,int exp)
{
if(u==dest)return exp;
for(int &i=work[u],v,tmp; i>=; i=Next[i])
if(flow[i]&&dis[v=ver[i]]==dis[u]+&&(tmp=Dinic_dfs(v,Min(exp,flow[i])))>)
{
flow[i]-=tmp;
flow[i^]+=tmp;
return tmp;
}
return ;
} int Dinic_flow()
{
int i,ret=,delta;
while(Dinic_bfs())
{
for(i=; i<node; ++i) work[i]=head[i];
while(delta=Dinic_dfs(src,oo)) ret+=delta; }
return ret;
} int main()
{
char s[];
int n,f,d,t;
while(scanf("%d%d%d",&n,&f,&d)==)
{
prepare(n*+f+d+,,n*+f+d+);
for(int i=; i<=f; i++)
{
scanf("%d",&t);
Addedge(,i,t);///源点加边
}
for(int i=; i<=d; i++)
{
scanf("%d",&t);
Addedge(f+*n+i,f+*n+d+,t);///汇点加边
}
for(int i=; i<=n; i++)
Addedge(f+i,f+n+i,);///拆点
for(int i=; i<=n; i++)
{
scanf("%s",s+);
for(int j=; j<=f; j++)
if(s[j]=='Y')
Addedge(j,f+i,);///顾客与食物加边
}
for(int i=; i<=n; i++)
{
scanf("%s",s+);
for(int j=; j<=d; j++)
if(s[j]=='Y')
Addedge(f+n+i,f+*n+j,);///顾客与饮料加边
}
printf("%d\n",Dinic_flow());
}
return ;
}

学长模板的链接:http://m.blog.csdn.net/article/details?id=30030439

模板:

#include<cstdio>
#include<iostream>
using namespace std;
const int oo=1e9; const int mm=;
const int mn=;
int node,src,dest,edge;
int ver[mm],flow[mm],next[mm];
int head[mn],work[mn],dis[mn],q[mn]; void prepare(int _node,int _src,int _dest) ///node是结点总数
{
node=_node,src=_src,dest=_dest;
for(int i=; i<node; ++i)head[i]=-;
edge=;
} void addedge(int u,int v,int c)
{
ver[edge]=v,flow[edge]=c,next[edge]=head[u],head[u]=edge++;
ver[edge]=u,flow[edge]=,next[edge]=head[v],head[v]=edge++;
} bool Dinic_bfs()
{
int i,u,v,l,r=;
for(i=; i<node; ++i)dis[i]=-;
dis[q[r++]=src]=;
for(l=; l<r; ++l)
for(i=head[u=q[l]]; i>=; i=next[i])
if(flow[i]&&dis[v=ver[i]]<)
{
dis[q[r++]=v]=dis[u]+;
if(v==dest)return ;
}
return ;
} int Dinic_dfs(int u,int exp)
{
if(u==dest)return exp;
for(int &i=work[u],v,tmp; i>=; i=next[i])
if(flow[i]&&dis[v=ver[i]]==dis[u]+&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>)
{
flow[i]-=tmp;
flow[i^]+=tmp;
return tmp;
}
return ;
}
int Dinic_flow()
{
int i,ret=,delta;
while(Dinic_bfs())
{
for(i=; i<node; ++i)work[i]=head[i];
while(delta=Dinic_dfs(src,oo))ret+=delta;
}
return ret;
}

SAP模板:

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
using namespace std; const int MAXN=;//点数的最大值
const int MAXM=**;//边数的最大值
const int INF=0x3f3f3f3f; struct Edge
{
int to,next,cap,flow;
} edge[MAXM]; //注意是MAXM int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN]; void init()
{
tol=;
memset(head,-,sizeof(head));
}
//加边,单向图三个参数,双向图四个参数
void addedge(int u,int v,int w,int rw=)
{
edge[tol].to = v;
edge[tol].cap = w;
edge[tol].next = head[u];
edge[tol].flow = ;
head[u] = tol++; edge[tol].to = u;
edge[tol].cap = rw;
edge[tol].next = head[v];
edge[tol].flow = ;
head[v]=tol++;
}
//输入参数:起点、终点、点的总数
//点的编号没有影响,只要输入点的总数
int sap(int start,int end,int N)
{
memset(gap,,sizeof(gap));
memset(dep,,sizeof(dep));
memcpy(cur,head,sizeof(head));
int u=start;
pre[u]=-;
gap[]=N;
int ans=;
while(dep[start]<N)
{
if(u==end)
{
int Min=INF;
for(int i=pre[u]; i!=-; i=pre[edge[i^].to])
if(Min>edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
for(int i=pre[u]; i!=-; i=pre[edge[i^].to])
{
edge[i].flow+=Min;
edge[i^].flow-=Min;
}
u=start;
ans+=Min;
continue;
}
bool flag=false;
int v;
for(int i=cur[u]; i!=-; i=edge[i].next)
{
v=edge[i].to;
if(edge[i].cap-edge[i].flow && dep[v]+==dep[u])
{
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if(flag)
{
u=v;
continue;
}
int Min=N;
for(int i=head[u]; i!=-; i=edge[i].next)
if(edge[i].cap-edge[i].flow && dep[edge[i].to]<Min)
{
Min=dep[edge[i].to];
cur[u]=i;
}
gap[dep[u]]--;
if(!gap[dep[u]])return ans;
dep[u]=Min+;
gap[dep[u]]++;
if(u!=start) u=edge[pre[u]^].to;
}
return ans;
} int main()
{
init();
addedge(u,v,value);
maxf=sap(,n+m+,n+m+); ///源点,汇点,总点数的值。
}

ISAP模板:

#include <cstdio>
#include <cstring> using namespace std; const int MAXN = ;
const int MAXM = ; // ISAP struct edge
{
int t, f;
edge *p, *r;
} T[MAXM], *H[MAXN], *I[MAXN], *P[MAXN]; int C;
int G[MAXN], D[MAXN], L[MAXN]; inline void adde(const int a, const int b, const int c)
{
edge *e1 = T + C++;
edge *e2 = T + C++;
e1->t = b;
e1->f = c;
e1->p = H[a];
e1->r = e2;
H[a] = e1;
e2->t = a;
e2->f = ;
e2->p = H[b];
e2->r = e1;
H[b] = e2;
} inline int isap(const int cnt, const int src, const int snk)
{
int maxf = ;
int curf = 0x3f3f3f3f;
int u = src, v;
edge *e;
memcpy(I, H, sizeof(H));
memset(G, , sizeof(G));
memset(D, , sizeof(D));
G[] = cnt;
while (D[src] < cnt)
{
L[u] = curf;
for (e = I[u]; e; e = e->p)
{
v = e->t;
if (e->f > && D[u] == D[v] + )
{
I[u] = P[v] = e;
if (e->f < curf)
curf = e->f;
u = v;
if (u == snk)
{
maxf += curf;
while (u != src)
{
P[u]->f -= curf;
P[u]->r->f += curf;
u = P[u]->r->t;
}
curf = 0x3f3f3f3f;
}
break;
}
}
if (e)
continue;
if (!--G[D[u]])
break;
int mind = cnt - ;
for (e = H[u]; e; e = e->p)
if (e->f > && D[e->t] < mind)
{
I[u] = e;
mind = D[e->t];
}
++G[D[u] = mind + ];
if (u != src)
{
u = P[u]->r->t;
curf = L[u];
}
}
return maxf;
} int N, M;
bool V[]; int main()
{
int tt, a, b, c, ss, cnt;
scanf("%d", &tt);
for (int tc = ; tc <= tt; ++tc)
{
memset(V, false, sizeof(V));
memset(H, , sizeof(H));
ss = ;
C = ;
scanf("%d%d", &N, &M);
cnt = N + ;
for (int i = ; i < N; ++i)
{
scanf("%d%d%d", &a, &b, &c);
adde(, i, a);
for (int j = b - ; j < c; ++j)
{
adde(i, j + , );
if (!V[j])
{
adde(j + , , M);
V[j] = true;
++cnt;
}
}
ss += a;
}
if (isap(cnt, , ) == ss)
printf("Case %d: Yes\n\n", tc);
else
printf("Case %d: No\n\n", tc);
}
return ;
}

hdu4292 Food 最大流模板题的更多相关文章

  1. HDU-3549 最大流模板题

    1.HDU-3549   Flow Problem 2.链接:http://acm.hdu.edu.cn/showproblem.php?pid=3549 3.总结:模板题,参考了 http://ww ...

  2. 【网络流#2】hdu 1533 - 最小费用最大流模板题

    最小费用最大流,即MCMF(Minimum Cost Maximum Flow)问题 嗯~第一次写费用流题... 这道就是费用流的模板题,找不到更裸的题了 建图:每个m(Man)作为源点,每个H(Ho ...

  3. 【网络流#1】hdu 3549 - 最大流模板题

    因为坑了无数次队友 要开始学习网络流了,先从基础的开始,嗯~ 这道题是最大流的模板题,用来测试模板好啦~ Edmonds_Karp模板 with 前向星 时间复杂度o(V*E^2) #include& ...

  4. POJ 1273 - Drainage Ditches - [最大流模板题] - [EK算法模板][Dinic算法模板 - 邻接表型]

    题目链接:http://poj.org/problem?id=1273 Time Limit: 1000MS Memory Limit: 10000K Description Every time i ...

  5. hdu 1532 Drainage Ditches(最大流模板题)

    Drainage Ditches Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. HDU-3549Flow Problem 最大流模板题

    传送门 这里是Ford-Fulkerson写的最大流模板 #include <iostream> #include <cstdio> #include <algorith ...

  7. POJ-2135 Farm Tour---最小费用最大流模板题(构图)

    题目链接: https://vjudge.net/problem/POJ-2135 题目大意: 主人公要从1号走到第N号点,再重N号点走回1号点,同时每条路只能走一次. 这是一个无向图.输入数据第一行 ...

  8. POJ2135 最小费用最大流模板题

    练练最小费用最大流 此外此题也是一经典图论题 题意:找出两条从s到t的不同的路径,距离最短. 要注意:这里是无向边,要变成两条有向边 #include <cstdio> #include ...

  9. 2018牛客网暑期ACM多校训练营(第五场) E - room - [最小费用最大流模板题]

    题目链接:https://www.nowcoder.com/acm/contest/143/E 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K ...

随机推荐

  1. WinMain名词解析

    WinMain程序名词解析 int WINAPI WinMain(HINSTANCE hInstance ,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nS ...

  2. HDU-1083Courses,二分图模板题!

    Courses                                                                                             ...

  3. hihoCoder#1036 Trie图

    原题地址 看了这篇博文,总算是把Trie图弄明白了 Runtime Error了无数次,一直不知道为什么,于是写了个脚本生成了一组大数据,发现果然段错误了. 调试了一下午,总算闹明白了,为什么呢? 1 ...

  4. noip模拟赛 道路分组

    分析:因为每一组编号都是连续的嘛,所以能分成一组的尽量分,每次加边后dfs判断一下1和n是否连通.有向图的判连通没有什么很快的方法,特别注意,并查集是错的!这个算法可以得到60分. 事实上每一次都不需 ...

  5. boot简介

    目录 1:bootloader介绍2:如何启动一个机器3:工具 Bootloader介绍 MTK的bootloader 主要分为Pre-loader, LK. Pre-loader: 初始化PLL,U ...

  6. Labeling Balls(poj 3687)

    题意:N个球,从1-N编号,质量不同,范围1-N,无重复.给出小球间的质量关系(<), 要求给每个球贴标签,标签表示每个球的质量.按编号输出每个球的标签.如果解不唯一,按编号小的质量小排. /* ...

  7. 营救(洛谷 P1396)

    题目描述 “咚咚咚……”“查水表!”原来是查水表来了,现在哪里找这么热心上门的查表员啊!小明感动的热泪盈眶,开起了门…… 妈妈下班回家,街坊邻居说小明被一群陌生人强行押上了警车!妈妈丰富的经验告诉她小 ...

  8. Mysql UPDATE 操作时含 Limit 注意事项

    在update时,可以使用limit来设置,更新的条数,但下面这句sql语句是错误的. LIMIT ,; //错误提示:ERROR 1064 (42000): You have an error in ...

  9. [NOIP2007] 普及组

    奖学金 模拟 开个struct排序即可 c++吼啊 /*by SilverN*/ #include<algorithm> #include<iostream> #include ...

  10. Operating system management of address-translation-related data structures and hardware lookasides

    An approach is provided in a hypervised computer system where a page table request is at an operatin ...