-
H - Food
HDU - 4292 - 题意:给定N个人、F种食物、M种饮料以及每种食物数量、每种饮料数量。
- 通过一个N*F的矩阵给出某个人是否接受某种食物。
- 再通过一个N*M矩阵给出某个人是否接受某种饮料。
- 顾客的要求是同时有饮料和食物(即其接受的饮料至少提供一瓶,接受的食物至少提供一份)。
- 求最多能满足多少位顾客。
- 思路:顾客同时需要满足饮料和食物两种需求,可以引一条从食物到顾客的有向弧、一条顾客到饮料的有向弧。那么每一条可行流都对应一个被满足的顾客,但不是一一对应。要满足一一对应关系,即顾客结点的结点容量为1,需要将顾客进行拆点。顾客u拆成u1和u2,u1、u2之间连一条容量为u结点容量的有向弧。原指向u的边改成指向u1,原从u指出的边改成从u2指出。
- 如此,将饮料看作源点、食物看作汇点,这就是一个多源多汇模型。每条流量对应一个被满足的顾客。
- 解决多源多汇模型,设立一个超级源点S,引入从S到源点的有向弧,容量为1.设立一个超级汇点T,引入汇点到超级汇点的有向弧,容量为1. 超级源点到超级汇点的最大流即为答案。
-
#include<bits/stdc++.h> using namespace std; #define maxn 2200 int d,n,f,a[maxn],b[maxn],deep[maxn]; int head[maxn],cnt,s,s1,sum; char c; struct node { int v,w,to; } edge[maxn*200]; void init() { cnt=-1; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { edge[++cnt].v=v; edge[cnt].to=head[u]; head[u]=cnt; edge[cnt].w=w; edge[++cnt].v=u; edge[cnt].to=head[v]; head[v]=cnt; edge[cnt].w=0; } bool dinic_bfs() { memset(deep,0,sizeof(deep)); queue<int>que; while(!que.empty())que.pop(); que.push(0); deep[0]=1; while(!que.empty()) { int u=que.front(); que.pop(); for(int i=head[u]; i!=-1; i=edge[i].to) { int v=edge[i].v; if(deep[v]==0&&edge[i].w>0) { deep[v]=deep[u]+1; que.push(v); } } } return deep[sum]!=0; } int dinic_dfs(int u,int cpflow) { if(u==sum)return cpflow; int addflow=0; for(int i=head[u]; i!=-1&&cpflow; i=edge[i].to) { int v=edge[i].v; if(deep[u]+1==deep[v]&&edge[i].w>0) { int temp=dinic_dfs(v,min(edge[i].w,cpflow-addflow)); if(temp>0) { edge[i].w-=temp; edge[i^1].w+=temp; addflow+=temp; } } } return addflow; } void dinic() { int maxflow=0; while(dinic_bfs()) { maxflow+=dinic_dfs(0,sum); } printf("%d\n",maxflow); } int main() { while(scanf("%d%d%d",&n,&f,&d)!=EOF) { init(); sum=n+f+n+d+1; s=n+f+n; s1=n+f; for(int i=1; i<=n; i++) add(f+i,s1+i,1); for(int i=1; i<=f; i++) { scanf("%d",&a[i]); add(0,i,a[i]); } for(int i=1; i<=d; i++) { scanf("%d",&b[i]); add(s+i,sum,b[i]); } for(int i=1; i<=n; i++) { getchar(); for(int j=1; j<=f; j++) { scanf("%c",&c); if(c=='Y') add(j,f+i,1); } } for(int i=1; i<=n; i++) { getchar(); for(int j=1; j<=d; j++) { scanf("%c",&c); if(c=='Y') add(s1+i,s+j,1); } } dinic(); } return 0; }
H - Food HDU - 4292 -网络流-拆点
猜你喜欢
转载自blog.csdn.net/BePosit/article/details/83957083
今日推荐
周排行