POJ3281 拆点 最大流 EK算法
来源:互联网 发布:酒店网络机顶盒案例 编辑:程序博客网 时间:2024/05/16 18:57
Description
Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others.
Farmer John has cooked fabulous meals for his cows, but he forgot to check his menu against their preferences. Although he might not be able to stuff everybody, he wants to give a complete meal of both food and drink to as many cows as possible.
Farmer John has cooked F (1 ≤ F ≤ 100) types of foods and prepared D (1 ≤ D ≤ 100) types of drinks. Each of his N (1 ≤ N ≤ 100) cows has decided whether she is willing to eat a particular food or drink a particular drink. Farmer John must assign a food type and a drink type to each cow to maximize the number of cows who get both.
Each dish or drink can only be consumed by one cow (i.e., once food type 2 is assigned to a cow, no other cow can be assigned food type 2).
Input
Lines 2..N+1: Each line i starts with a two integers Fi and Di, the number of dishes that cow i likes and the number of drinks that cow i likes. The next Fi integers denote the dishes that cow i will eat, and the Di integers following that denote the drinks that cow i will drink.
Output
Sample Input
4 3 32 2 1 2 3 12 2 2 3 1 22 2 1 3 1 22 1 1 3 3
Sample Output
3
Hint
Cow 1: no meal
Cow 2: Food #2, Drink #2
Cow 3: Food #1, Drink #1
Cow 4: Food #3, Drink #3
The pigeon-hole principle tells us we can do no better since there are only three kinds of food or drink. Other test data sets are more challenging, of course.
今天开始刷kuangbin的最大流专题 发现根本做不动...
这道题也是网上查看了题解才会做的
思路:
建立一个超级源点和一个超级汇点 源点用编号0表示 汇点用2*n+f+d+1表示
食物用1~f 表示 饮料用2*n+f+1~2*n+f+d表示
将牛拆点 拆为两组 第一组编号为f+1~f+n 第二组为 f+n+1~f+2*n 自己与自己相连
将源点与食物相连 食物再与第一组牛相连 第一组牛与第二组牛相连 第二组牛与饮料相连(边的权值也为1) 再将饮料连到汇点
这样的作用是什么呢 例如1号牛与1号牛自己相连(也就是结点f+1与结点f+n+1相连) 并把这条边的值设置为1
这就表明 流在流的过程中 第二组牛只能只能选择1杯饮料 因为f+1到f+n+1这条边最大的流量就是1
这样就解决了一只牛可以对应多杯饮料的情况
#include<algorithm>#include<iostream>#include<cstdlib>#include<cstring>#include<cstdio>#include<string>#include<stack>#include<queue>#include<cmath>#include<stack>#include<list>#include<map>#include<set>typedef long long ll;using namespace std;int cap[405][405];int pre[405];int flow[405];int m;int bfs(int s,int e){ queue<int>q; int i; memset(pre,-1,sizeof pre); flow[s]=0x3f3f3f3f; pre[s]=0; q.push(s); while(!q.empty()) { int k=q.front(); q.pop(); if(k==e)break; for(i=0;i<=e;i++) { if(i!=s&&pre[i]==-1&&cap[k][i]) { pre[i]=k; flow[i]=min(flow[k],cap[k][i]); q.push(i); } } } if(pre[e]==-1)return -1; return flow[e];}int max_flow(int s,int e){ int inc=0; int flow1=0; while((inc=bfs(s,e))!=-1) { int k=e; while(k!=s) { int last=pre[k]; cap[last][k]-=inc; cap[k][last]+=inc; k=last; } flow1+=inc; } return flow1;}int main(){ int n,f,d; int i,j,k; while(scanf("%d%d%d",&n,&f,&d)==3)//f是食物 d是饮料 { memset(cap,0,sizeof cap); memset(flow,0,sizeof flow); int source=0; //源点 int sink=2*n+f+d+1; //汇点 for(i=1;i<=f;i++) cap[source][i]=1; //食物 是1到f for(i=2*n+f+1;i<=2*n+f+d;i++)cap[i][sink]=1; //饮料是 2*n+f+1 到2*n+f+d for(i=f+1;i<=f+n;i++)cap[i][i+n]=1; //牛与牛自己相连 for(i=1;i<=n;i++) { int drink,eat; scanf("%d%d",&eat,&drink); while(eat--) { int t; scanf("%d",&t); cap[t][i+f]=1; } while(drink--) { int t; scanf("%d",&t); cap[f+n+i][2*n+f+t]=1; } } m=sink; printf("%d\n",max_flow(source,sink)); } return 0;}
- POJ3281 拆点 最大流 EK算法
- POJ3281 Dining,最大流EK算法
- poj3281--Dining(最大流(EK算法))
- (拆点+最大流)POJ3281 Dining
- POJ3281 Dining (拆点+最大流)
- 最大流EK算法
- 最大流EK算法
- 最大流-EK算法
- 最大流-EK算法
- poj3281 Dining(经典最大流+拆点)
- POJ3436--ACM Computer Factory--拆点EK算法求最大流
- poj3281--网络流 + 拆点
- poj3281 拆点+网络流
- 最大流EK算法模板
- 最大流 EK算法详解
- hdu1532 最大流 EK算法
- 图论 最大流EK算法
- 最大网络流 EK 算法
- SpringBootDemo
- 【OpenCV】中的KMeans算法介绍与应用(一)
- 2.2.2特例 基本类型
- 用for循环实现冒泡排序
- Python+Pandas 获取数据库并加入DataFrame
- POJ3281 拆点 最大流 EK算法
- JZOJ 1322. 硬币游戏
- xADC
- 用Wireshark保存RTP的负载码流
- POJ 3254 Corn Fields 状压dp入门
- Servlet基础笔记_17-07-05
- 网络编程(基于winsocket)-- 常用函数介绍(二)
- Scala练习-哈希查找
- 变量-常量