poj 3281 最大流
2015-09-07 14:31
405 查看
poj 3281
题意:每只奶牛喜欢吃若干种食物和饮料,问只吃一种食物和饮料的奶牛最多有多少只。
思路:将奶牛做点拆开,形成源点-食物-奶牛(左)-奶牛(右)-饮料-汇点的链,每条边的容量都是1,奶牛(左)-奶牛(右)限制了一只奶牛同时最多吃一种食物喝一种饮料。
然后跑最大流就可以了。
题意:每只奶牛喜欢吃若干种食物和饮料,问只吃一种食物和饮料的奶牛最多有多少只。
思路:将奶牛做点拆开,形成源点-食物-奶牛(左)-奶牛(右)-饮料-汇点的链,每条边的容量都是1,奶牛(左)-奶牛(右)限制了一只奶牛同时最多吃一种食物喝一种饮料。
然后跑最大流就可以了。
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h> #include <stdlib.h> #include <time.h> using namespace std; const int MAXN = 1010;//点数的最大值 const int MAXM = 400010;//边数的最大值 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 = 0; memset(head,-1,sizeof(head)); } //加边,单向图三个参数,双向图四个参数 void addedge(int u,int v,int w,int rw=0){ edge[tol].to = v;edge[tol].cap = w;edge[tol].next = head[u]; edge[tol].flow = 0;head[u] = tol++; edge[tol].to = u;edge[tol].cap = rw;edge[tol].next = head[v]; edge[tol].flow = 0;head[v]=tol++; } int sap(int start,int ed,int N){ memset(gap,0,sizeof(gap)); memset(dep,0,sizeof(dep)); memcpy(cur,head,sizeof(head)); int u = start; pre[u] = -1; gap[0] = N; int ans = 0; while(dep[start] < N){ if(u == ed){ int Min = INF; for(int i = pre[u];i != -1; i = pre[edge[i^1].to]) if(Min > edge[i].cap - edge[i].flow) Min = edge[i].cap - edge[i].flow; for(int i = pre[u];i != -1; i = pre[edge[i^1].to]){ edge[i].flow += Min; edge[i^1].flow -= Min; } u = start; ans += Min; continue; } bool flag = false; int v; for(int i = cur[u]; i != -1;i = edge[i].next){ v = edge[i].to; if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]){ flag = true; cur[u] = pre[v] = i; break; } } if(flag){ u = v; continue; } int Min = N; for(int i = head[u]; i != -1;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+1; gap[dep[u]]++; if(u != start) u = edge[pre[u]^1].to; } return ans; } int main() { int n, f, d; while(~scanf("%d %d %d", &n, &f, &d)) { init(); for(int i = 1; i <= f; i++) addedge(1, n + n + i + 1, 1); for(int i = 1; i <= d; i++) addedge(i + 1 + n + n + f, 2 + n + n + f + d, 1); for(int i = 1; i <= n; i++) addedge(1 + i, 1 + n + i, 1); for(int i = 1; i <= n; i++){ int fi, di; scanf("%d %d", &fi, &di); while(fi--){ int a; scanf("%d", &a); addedge(n + n + 1 + a, 1 + i, 1); } while(di--){ int a; scanf("%d", &a); addedge(1 + n + i, 1 + n + n + f + a, 1); } } printf("%d\n", sap(1, n + n + f + d + 2, n + n + f + d + 2)); } }
相关文章推荐
- SDP协议分析
- 解决ListView在ScrollView里只显示单行的问题
- Scala开发入门教程
- IMEI/MEID校验位计算
- IOS_UI_TouchView
- 揭开HTTP网络协议神秘面纱系列(二)
- 2015-09-07 博客园 一个新的开始
- spring scope
- 十大单身狗最需要的APP
- gcc 后 -l 和 -L的区别
- 09/05作业
- C#学习之抽象类和方法
- BroadcastReceiver广播的各种使用方式
- 初探swift语言的学习笔记四(类对象,函数)
- 如何修改屏幕最低的亮度值
- hue 安装笔记
- 数组的懒加载
- 移动端前端开发总结(1) 拉勾网前端开发学习
- jax-ws (1) cllient
- 初探swift语言的学习笔记三(闭包-匿名函数)