POJ 3281:Dining
来源:互联网 发布:网络层有哪些功能 编辑:程序博客网 时间:2024/06/06 01:45
题目链接:http://poj.org/problem?id=3281
题目翻译:农夫约翰为它的牛准备了F种食物,D种饮料,每头牛有自己
喜欢的食物和饮料,而每种食物只能分配给一头牛,最多能有多少头牛
可以同时得到喜欢的食物和饮料?
解题思路:
构建网络流:
边的方向 S(超级源点)->食物(F种食物)->牛->牛->饮料(D种饮料)
其中牛到牛是拆点,而且这个题目必须拆点,这个题目是最大流题目,
它属于顶点上有容量限制的最大流,对于容量有限制的顶点,我们必须
要拆点,这个边的容量就是顶点的容量。和POJ 3436:ACM Computer Factory
是一样的,都要拆点,原来我还不太明白为什么非要拆点,但是看了挑战程序
设计之后明白了,拆点之后就达到了限流的作用。否则对于一头牛它有可能
会得到多于一组的食物和饮料的搭配。
AC代码:
#include <iostream>#include <stdio.h>#include <string.h>#include <queue>#include <vector>using namespace std;const int maxn = 500;const int INF = 0x3f3f3f3f;int N,F,D; ///F种食物,D种饮料,N头牛int S,T; ///超级源点,超级汇点。int cap[maxn][maxn]; ///容量int level[maxn],vis[maxn];int maxFlow;///广搜分层bool bfs(){ queue<int>qu; memset(level,-1,sizeof(level)); level[S] = 0; qu.push(S); while(!qu.empty()) { int u = qu.front(); qu.pop(); for(int i = 0; i <= T; i++) { if(level[i]==-1 && cap[u][i]>0) { level[i] = level[u] + 1; if(i == T) return true; qu.push(i); } } } return false;}///求增广路径void dfs(){ int u,v,cur,i; deque<int>qu; ///双端队列,当作栈用 memset(vis,0,sizeof(vis)); vis[S] = 1; qu.push_back(S); while(!qu.empty()) { cur = qu.back(); if(cur == T) { for(i = 1; i < (int)qu.size(); i++) { u = qu[i-1]; v = qu[i]; cap[u][v] -= 1; cap[v][u] += 1; vis[v] = 0; ///直接取消标记 } maxFlow += 1; ///图中有权值为1或0的边,座椅一条路中的最大最小流量都是1. qu.clear(); qu.push_back(S); ///这种情况其实每次都是从S开始回溯的,因为找到一条路后,这整条路就断了。 } else { for(i = 1; i <= T; i++) { if(cap[cur][i]>0 && level[i] == level[cur]+1 && vis[i]==0) { vis[i] = 1; qu.push_back(i); break; } } if(i > T) qu.pop_back(); } }}void dinic(){ maxFlow = 0; while(bfs()) { dfs(); } printf("%d\n",maxFlow);}int main(){ while(~scanf("%d%d%d",&N,&F,&D)) ///N牛的数量,F食物种类,D饮料种类 { S = 0; ///超级源点 T = 2*N+F+D+1; ///超级汇点 ///0是超级源点,1~2*N是牛拆点,2*N+1~2*N+F是食物,2*N+F+1~2*N+F+D是饮料 memset(cap,0,sizeof(cap)); ///超级源点向每种食物引一条边 for(int i = 2*N+1; i <= 2*N+F; i++) { cap[S][i] = 1; } ///每种饮料向超级汇点引一条边 for(int i = 2*N+F+1; i <= 2*N+F+D; i++) { cap[i][T] = 1; } ///每个牛拆成两个点,来达到限流的目的 for(int i = 1; i <= N; i++) { cap[i][i+N] = 1; } int food,drink; for(int i = 1; i <= N; i++) { scanf("%d%d",&food,&drink); int u; for(int j = 1; j <= food; j++) { scanf("%d",&u); ///食物向原来牛的点引边,食物编号2*N+u u = 2*N+u; cap[u][i] = 1; } for(int j = 1; j <= drink; j++) { scanf("%d",&u); ///从牛拆出的点向饮料引边,牛的编号i+N,音量编号2*N+F+u u = 2*N+F+u; cap[i+N][u] = 1; } } dinic(); } return 0;}
阅读全文
0 0
- poj 3281 Dining Maxflow
- POJ 3281 Dining
- poj 3281 Dining //SAP
- POJ 3281 Dining
- poj 3281 Dining
- poj 3281 Dining
- POJ 3281 Dining
- POJ 3281 Dining
- poj 3281 Dining
- POJ-3281-Dining
- poj(3281)Dining
- POJ 3281 Dining
- poj 3281 Dining
- poj 3281 Dining
- POJ 3281 Dining
- POJ 3281 Dining
- POJ 3281 Dining dinic
- POJ 3281 — Dining
- as NDK mk文件项目目录
- Linux基础01-介绍与NAT通信
- EM和GMM
- springboot系列(第一讲)
- Python-uiautomator使用说明文档
- POJ 3281:Dining
- 常见的event事件
- sql server如何将高版本的数据迁移到低版本中。解决数据库 'XX' 的版本为 655,无法打开。此服务器支持 611 版及...
- 关于springboot访问页面
- java向上转型和向下转型
- 【学习笔记】TensorFlow 入门之基本使用
- C++不要在构造函数和析构函数中调用virtual函数的原因
- 【OpenJ 2987】T3 小兔子捡金币(小金币捡兔子)
- keil5 点击build 每次都全编译