【poj3281】【最大流】Dining

来源:互联网 发布:淘宝双十一 实时 编辑:程序博客网 时间:2024/05/16 21:38

一道最大流的简单题。将食物和饮料分别看成一个点集,食物放在左边(记为f[i]),饮料放在右边(记为d[i])然后将牛拆成两个点k,k'

然后开始建图

1、对于每头牛喜欢的食物和饮料:添加edge(f[i],k,1),edge(d[i],k',1),edge(k,k',1),这样做的目的是为了限制每头牛只能享用一种食物和饮料。

2、对于每个食物和饮料:添加edge(s,f[i],1),edge(d[i],t,1),这样做的目的是限制一种食物和饮料只能选一次。

这样在原图上做一次最大流即为所求,要注意的是拆点时一定要注意好点的映射关系,不重复映射

代码:

#include<cstdio>#include<cstring>using namespace std;const int inf = 0x3f3f3f3f;const int maxn = 500;const int maxm = 50000;struct Edge{int c,pos;int next;}E[maxm];int dis[maxn],gap[maxn],pre[maxn],cur[maxn];int head[maxn];int NE = 0;int n,f,d,add;int s,t,nodenum;void init(){freopen("poj3281.in","r",stdin);freopen("poj3281.out","w",stdout);}void insert(int u,int v,int c){E[NE].c = c;E[NE].pos = v;E[NE].next = head[u];head[u] = NE++;E[NE].c = 0;E[NE].pos = u;E[NE].next = head[v];head[v] = NE++;}inline void checkmin(int &a,int b){if(a == -1 || a > b)a = b;}void readdata(){memset(head,-1,sizeof(head));scanf("%d%d%d",&n,&f,&d);add = (n << 1);for(int i = 1;i <= n;i++){int fo,dr;scanf("%d%d",&fo,&dr);for(int j = 1;j <= fo;j++){int tmp;scanf("%d",&tmp);insert(tmp + add,i,1);}for(int j = 1;j <= dr;j++){int tmp;scanf("%d",&tmp);insert(i + n,tmp + add + f,1);}insert(i,i + n,1);}}int sap(){memset(dis,0,sizeof(dis));memset(gap,0,sizeof(gap));for(int i = s;i <= t;i++)cur[i] = head[i];int u = pre[s] = s,maxflow = 0,aug = -1;gap[0] = nodenum;while(dis[s] < nodenum){loop:   for(int &i = cur[u];i != -1;i = E[i].next){int v = E[i].pos;if(E[i].c && dis[u] == dis[v] + 1){checkmin(aug,E[i].c);pre[v] = u;u = v;if(v == t){maxflow += aug;for(u = pre[u];v != s;v = u,u = pre[u]){E[cur[u]].c -= aug;E[cur[u]^1].c += aug;}aug = -1;}goto loop;}}int mind = nodenum;for(int i = head[u];i != -1;i = E[i].next){int v = E[i].pos;if(E[i].c && (mind > dis[v])){cur[u] = i;mind = dis[v];}}if((--gap[dis[u]]) == 0)break;gap[dis[u] = mind + 1]++;u = pre[u];}return maxflow;}void solve(){s = 0,t = n * 2 + f + d + 1;nodenum = t + 1;for(int i = 1;i <= f;i++)insert(s,i + add,1);for(int i = 1;i <= d;i++)insert(i + add + f,t,1);printf("%d\n",sap());}int main(){init();readdata();solve();return 0;}



原创粉丝点击