网络流最大流的优化算法Dicnic,每一步对原图进行分层,然后用DFS求增广路。时间复杂度是O(n^2*m) 。

Poj 3281 和 9.16号成都regional网络赛food那道题,都是很好的模板题。。

以food那题为例,这样建图:设一个源点,每一种food为一层,每个人分成两部分,people1 people2两层,每种饮料是一层,然后是一个汇点。

每一种食物的个数,即为源点到那种food的流量;

饮料同理。

每一个人只消耗一种一个食物和一种一个饮料,因此每种食物(或饮料)与人的连线,流量为1

people1与people2的间的流量为1

模板放这儿先。

POJ 3281

#include<stdio.h>
#include<string.h>
const int EDGE_NUM = 20001;//边数
const int POINT_NUM = 501;//点数
struct edge
{int v;//点int next;//下一边int value;//当前边流量
} edge[2*EDGE_NUM]; //边信息,以邻接表形式存储int p[POINT_NUM];//p[i]记录最后一条以i为起点的边的id,即以i为起点的最后一条边为edge[p[i]],而edge[p[i]].next则为以i为起点的倒数第二条边,以此类推
int level[POINT_NUM];//level[i]记录i点的层次
int que[POINT_NUM],out[POINT_NUM];//辅助数组
int edgeNumber;void init()
{edgeNumber = 0;memset(p,-1,sizeof(p));
}inline void addEdge(int from,int to,int value)//添加边,以邻接表形式存储
{edge[edgeNumber].v = to;edge[edgeNumber].value = value;edge[edgeNumber].next = p[from];p[from] = edgeNumber++;
}int Dinic(int source,int sink,int n)
{int i,maxFlow = 0;while(true){int head,tail;for(i=0; i<n; i++)level[i] = 0;level[source] = 1;//源点为第一层head = 0;tail = 0;que[0] = source;//que这里当队里使用while(head<=tail)//BFS该剩余图,计算每个可达点层次{int cur = que[head++];for(i=p[cur]; i!=-1; i=edge[i].next){if(edge[i].value>0&&level[edge[i].v]==0){level[edge[i].v] = level[cur]+1;que[++tail] = edge[i].v;}}}if(level[sink]==0)break;//不存在增广路for(i=0; i<n; i++)out[i]=p[i]; //out[i]动态记录可用边int q = -1;//q为已经搜索到的点的个数,que存放途径边信息while(true)//DFS剩余图,查找增广路{if(q<0)//当前路为空{int cur = out[source];for(; cur!=-1; cur=edge[cur].next) //查找第一条边{if(edge[cur].value>0&&out[edge[cur].v]!=-1&&level[edge[cur].v]==2)//合法第一条边必须满足:1.流量大于0;2.终点有可用边 3:终点层次为2break;}if(cur==-1)break;//找不到第二层,当前剩余图已经没有增广路que[++q]=cur;//存入第一条边idout[source]=edge[cur].next;}int curnode = edge[que[q]].v;//当前路的终点if(curnode==sink)//找到一条增广路{int thisflow = edge[que[0]].value;//thisflow为当前增广路的流量int index = 0;//标记最小流量边的idfor(i=1; i<=q; i++){if(thisflow>edge[que[i]].value){thisflow=edge[que[i]].value;index = i;}}maxFlow+=thisflow;for(i=0; i<=q; i++){edge[que[i]].value-=thisflow;edge[que[i]^1].value+=thisflow;//与其方向相反的边}q = index-1;//查找下一条增广路时可直接使用当前路的前q条边}else//尚未找到汇点{int cur = out[curnode];for(; cur!=-1; cur=edge[cur].next){if(edge[cur].value>0&&out[edge[cur].v]!=-1&&level[edge[cur].v]==level[curnode]+1)break;}if(cur==-1)//没有下一条路{out[curnode]=-1;//标记当前点的可达边为0q--;}else{que[++q]=cur;out[curnode]=edge[cur].next;//下一次搜索时可达边从edge[cur].next开始查找}}}}return maxFlow;
}int main()
{int Nn,Ff,Dd;while(scanf("%d%d%d",&Nn,&Ff,&Dd)!=EOF){init();int foodstart = 1;int cow1 = Ff+2;int cow2 = cow1+Nn+1;int drinkstart = cow2+Nn+1;int end = drinkstart+Dd+1;int i;for(i=0; i<Nn; i++) //添加牛边{addEdge(cow1+i,cow2+i,1);addEdge(cow2+i,cow1+i,0);}for(i=0; i<Ff; i++) //添加食物边{addEdge(0,foodstart+i,1);       addEdge(foodstart+i,0,0);}for(i=0; i<Dd; i++) //添加饮料{addEdge(drinkstart+i,end,1); addEdge(end,drinkstart+i,0);}for(i=0; i<Nn; i++){int f,d;scanf("%d%d",&f,&d);int x;while(f--){scanf("%d",&x);x--;addEdge(foodstart+x,cow1+i,1);addEdge(cow1+i,foodstart+x,0);}while(d--){scanf("%d",&x);x--;addEdge(cow2+i,drinkstart+x,1);addEdge(drinkstart+x,cow2+i,0);}}printf("%d\n",Dinic(0,end,end+1));}return 0;
}

成都regional网络赛

#include<cstdio>
#include<cstring>
#include <memory.h>
const int EDGE_NUM = 100001;//边数
const int POINT_NUM = 250;//点数
struct edge
{int v;//点int next;//下一边int value;//当前边流量
} edge[2*EDGE_NUM]; //边信息,以邻接表形式存储int p[POINT_NUM];//p[i]记录最后一条以i为起点的边的id,即以i为起点的最后一条边为edge[p[i]],而edge[p[i]].next则为以i为起点的倒数第二条边,以此类推
int level[POINT_NUM];//level[i]记录i点的层次
int que[POINT_NUM],out[POINT_NUM];//辅助数组
int edgeNumber;
int food[250];
int drink[250];
void init()
{edgeNumber = 0;memset(p,-1,sizeof(p));
}
void addEdge(int from,int to,int value)//添加边,以邻接表形式存储
{edge[edgeNumber].v = to;edge[edgeNumber].value = value;edge[edgeNumber].next = p[from];p[from] = edgeNumber++;
}int Dinic(int source,int sink,int n)
{int i,maxFlow = 0;while(true){int head,tail;for(i=0; i<n; i++)level[i] = 0;level[source] = 1;//源点为第一层head = 0;tail = 0;que[0] = source;//que这里当队里使用while(head<=tail)//BFS该剩余图,计算每个可达点层次{int cur = que[head++];for(i=p[cur]; i!=-1; i=edge[i].next){if(edge[i].value>0&&level[edge[i].v]==0){level[edge[i].v] = level[cur]+1;que[++tail] = edge[i].v;}}}if(level[sink]==0)break;//不存在增广路for(i=0; i<n; i++)out[i]=p[i]; //out[i]动态记录可用边int q = -1;//q为已经搜索到的点的个数,que存放途径边信息while(true)//DFS剩余图,查找增广路{if(q<0)//当前路为空{int cur = out[source];for(; cur!=-1; cur=edge[cur].next) //查找第一条边{if(edge[cur].value>0&&out[edge[cur].v]!=-1&&level[edge[cur].v]==2)//合法第一条边必须满足:1.流量大于0;2.终点有可用边 3:终点层次为2break;}if(cur==-1)break;//找不到第二层,当前剩余图已经没有增广路que[++q]=cur;//存入第一条边idout[source]=edge[cur].next;}int curnode = edge[que[q]].v;//当前路的终点if(curnode==sink)//找到一条增广路{int thisflow = edge[que[0]].value;//thisflow为当前增广路的流量int index = 0;//标记最小流量边的idfor(i=1; i<=q; i++){if(thisflow>edge[que[i]].value){thisflow=edge[que[i]].value;index = i;}}maxFlow+=thisflow;for(i=0; i<=q; i++){edge[que[i]].value-=thisflow;edge[que[i]^1].value+=thisflow;//与其方向相反的边}q = index-1;//查找下一条增广路时可直接使用当前路的前q条边}else//尚未找到汇点{int cur = out[curnode];for(; cur!=-1; cur=edge[cur].next){if(edge[cur].value>0&&out[edge[cur].v]!=-1&&level[edge[cur].v]==level[curnode]+1)break;}if(cur==-1)//没有下一条路{out[curnode]=-1;//标记当前点的可达边为0q--;}else{que[++q]=cur;out[curnode]=edge[cur].next;//下一次搜索时可达边从edge[cur].next开始查找}}}}return maxFlow;
}int main()
{int Nn,Ff,Dd;while(scanf("%d%d%d",&Nn,&Ff,&Dd)!=EOF){init();int foodstart = 1;int cow1 = Ff+1;int cow2 = cow1+Nn+1;int drinkstart = cow2+Nn+1;int end = drinkstart+Dd+1;for(int i=1;i<=Ff;i++)scanf("%d",&food[i]);for(int i=1;i<=Dd;i++)scanf("%d",&drink[i]);int i;for(i=0; i<Nn; i++) //添加牛边{addEdge(cow1+i,cow2+i,1);addEdge(cow2+i,cow1+i,0);}for(i=0; i<Ff; i++) //添加食物边{addEdge(0,foodstart+i,food[i+1]); //每一种食物路径的流量。addEdge(foodstart+i,0,0);}for(i=0; i<Dd; i++) //添加饮料{addEdge(drinkstart+i,end,drink[i+1]);addEdge(end,drinkstart+i,0);}char t;for(i=0; i<Nn; i++){getchar();for(int j=0; j<Ff; j++){scanf("%c",&t);if(t=='Y'){addEdge(foodstart+j,cow1+i,1);addEdge(cow1+i,foodstart+j,0);}}}for(i=0; i<Nn; i++){getchar();for(int j=0; j<Dd; j++){scanf("%c",&t);if(t=='Y'){addEdge(cow2+i,drinkstart+j,1);addEdge(drinkstart+j,cow2+i,0);}}}printf("%d\n",Dinic(0,end,end+1));}return 0;
}

转载于:https://www.cnblogs.com/MicZ/archive/2012/09/17/2785369.html

Poj 3281 Regional Chengdu Food(Dicnic)相关推荐

  1. POJ 3268 Silver Cow Party (最短路径)

    POJ 3268 Silver Cow Party (最短路径) Description One cow from each of N farms (1 ≤ N ≤ 1000) convenientl ...

  2. POJ 计算几何入门题目推荐(转)

    POJ 计算几何入门题目推荐(转)       其实也谈不上推荐,只是自己做过的题目而已,甚至有的题目尚未AC,让在挣扎中.之所以推荐计算几何题,是因为,本人感觉ACM各种算法中计算几何算是比较实际的 ...

  3. POJ 3278 Catch That Cow(BFS)

    题目网址:http://poj.org/problem?id=3278 题目: Catch That Cow Time Limit: 2000MS   Memory Limit: 65536K Tot ...

  4. POJ 1363 火车厢排队问题(栈)

    题目链接:http://poj.org/problem?id=1363 题目大意: A站有编号为1到N,N最大1000,的车厢,车厢进入中转station了就不能回到A,只能停在station内或者进 ...

  5. POJ 1664 苹果放盘子(递归)

    题目链接:http://poj.org/problem?id=1664 m个相同的苹果放在n个相同的盘子里,有多少种不一样的方法. 例如,3个苹果放在4个盘子里有(3,0,0,0)(1,1,1,0)( ...

  6. POJ 3126 - Prime Path + Python(BFS)

    ()原题链接: # 原题:POJ 3126 - Prime Path | 眈眈探求 # 解题思路:https://blog.csdn.net/LYHVOYAGE/article/details/182 ...

  7. poj 3579 Median 中间值(二分搜索)

    Given N numbers, X1, X2, ... , XN, let us calculate the difference of every pair of numbers: ∣Xi - X ...

  8. POJ 1904 King's Quest(强连通图)题解

    题意:n个王子有自己喜欢的ki个公主,有n个公主,每个王子只能娶一个自己喜欢的公主且不能绿别的王子.现在给你一种王子娶公主的方案,并且保证这种方案是正确的.请你给出,每个王子能娶哪些公主,要求娶这些公 ...

  9. 【POJ - 2376】Cleaning Shifts (贪心)

    题干: Farmer John is assigning some of his N (1 <= N <= 25,000) cows to do some cleaning chores ...

最新文章

  1. ViSP安装与配置VS工程(常见方式-VS2019属性页方法)
  2. KingPaper初探Java之方法声明及重载
  3. Ciruy英雄谭 Chapter 3 杂谈
  4. PolarFS :一个用于共享存储云数据库的超低延迟和容错分布式文件系统
  5. 全程图解:Centos 5.2 下 ORACLE10G 安装配置
  6. linux练习手册,Linux操作习题集(1)
  7. Spring Boot笔记-对dto数据传输对象及物联网公司主创建主键的认识
  8. TypeScript学习笔记(五) - 泛型
  9. 动态添加table表格内容,填充审批意见。
  10. window10耳机插入没有声音,电脑里没有Realtek 高清晰音频管理器解决方法
  11. 二值图像分析—轮廓发现
  12. kubectl rollout restart 命令“unkonw command“
  13. 平均 15144 元、软件工程师占比最高,2021 年 2 月程序员工资最新出炉!
  14. 使用yum安装java
  15. java.lang.NoClassDefFoundError: org/dom4j/io/SAXReader
  16. 秋从饶合似陶家,遍绕篱边日渐斜。不是花中偏爱菊,此花开尽更无花
  17. 120篇精华文章打包送,干货慎入!
  18. 浅谈大数据背景下数据库安全保障体系
  19. c语言画笔的使用方法,新手必看:Photoshop笔刷画笔工具基本使用教程
  20. EN 45545-2:2020 T11烟毒性检测

热门文章

  1. cesium加载百度地图_Cesium专栏-百度地图加载(附源码下载)
  2. Spring Boot笔记-mysql5.7使用@Table后提示doesn't exist问题
  3. SQL工作笔记-达梦存储过程及时间触发器实现自动生成数据
  4. C++ opengl 线段的绘制
  5. 大三软件工程小项目-小技术集合-tcp服务器搭建及客户端
  6. php 在字符串中 找数字,php提取字符串中的数字
  7. bcdedit添加linux引导,Linux_利用Bcdedit创建Linux系统引导,Bcdedit在Windows Vista中的一个命 - phpStudy...
  8. 白鹭php源码,白鹭/CDNDrive
  9. mysql sql select for update_mysql SELECT FOR UPDATE语句使用示例
  10. c语言autoi函数如何使用,C++的auto声明、memset函数