poj 1149 PIGS【最大流经典建图】
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 18727 | Accepted: 8508 |
Description
All data concerning customers planning to visit the farm on that particular day are available to Mirko early in the morning so that he can make a sales-plan in order to maximize the number of pigs sold.
More precisely, the procedure is as following: the customer arrives, opens all pig-houses to which he has the key, Mirko sells a certain number of pigs from all the unlocked pig-houses to him, and, if Mirko wants, he can redistribute the remaining pigs across the unlocked pig-houses.
An unlimited number of pigs can be placed in every pig-house.
Write a program that will find the maximum number of pigs that he can sell on that day.
Input
The next line contains M integeres, for each pig-house initial number of pigs. The number of pigs in each pig-house is greater or equal to 0 and less or equal to 1000.
The next N lines contains records about the customers in the following form ( record about the i-th customer is written in the (i+2)-th line):
A K1 K2 ... KA B It means that this customer has key to the pig-houses marked with the numbers K1, K2, ..., KA (sorted nondecreasingly ) and that he wants to buy B pigs. Numbers A and B can be equal to 0.
Output
Sample Input
- 3 3
- 3 1 10
- 2 1 2 2
- 2 1 3 3
- 1 2 6
Sample Output
- 7
- 网络流问题的难点还是在于建图
- 题意:一个工人在养猪场工作,他负责卖猪,现在有m个猪圈和n个顾客,每个猪圈的容量没有限制,但是工人没有猪圈的钥匙,而前来的顾客有这些猪圈中一些猪圈的钥匙,每个顾客来之后会打开所有他有钥匙的猪圈,然后买完自己想要买的猪的个数后,关闭所有他打开的猪圈,顾客总是一个接一个的来,当猪圈打开的时候,工人可以随意挪动打开的猪圈中的猪(只能在打开的猪圈中相互移动)问工人一天最多卖出去多少猪
- 输入:开头第一行两个整数m,n分别代表猪圈数和顾客数,接下来一行m个数分别表示对应的猪圈中猪的个数,在接下来n行每行第一个数a,表示接下来a个数意思是当前行(第i行)i顾客所持的猪圈的钥匙,最后一个数b代表这个顾客要买b头猪
- 题解:1、超级源点连接第一个到达j猪圈的顾客 权值为第j个猪圈的猪的头数,
2、因为每个同时打开的猪圈之间的猪可以相互走动,所以所有连接到j猪圈的顾客相互连接容量为无穷大
3、处理重边,比如说第一个猪圈的第一个顾客和第二个猪圈的第一个顾客都是cus1,第三个猪圈的第一个顾客是cus2,所以就有源点到cus1的重边,此时将这两条边合并即可,流量为二者流量和
4、每一个顾客连接超级汇点
- #include<stdio.h>
- #include<string.h>
- #include<stack>
- #include<queue>
- #include<algorithm>
- #include<vector>
- #define MAXM 100100
- #define MAX 10010
- #define INF 0x7ffff
- using namespace std;
- vector<int>map[MAXM];
- int n,m,a,b[MAX];
- int ans,head[MAX];
- int cur[MAX],dis[MAX];
- int vis[MAX];
- int pig[MAX];
- struct node
- {
- int from,to,cap,flow,next;
- }edge[MAXM];
- void init()
- {
- ans=0;
- memset(head,-1,sizeof(head));
- for(int i=1;i<=m;i++)
- map[i].clear();
- }
- void add(int u,int v,int w)
- {
- int i,j;
- for(i=head[u];i!=-1;i=edge[i].next)
- {
- if(edge[i].to==v) //判断是否有重边
- break;
- }
- if(i==-1)//i==-1表示当前这个点并没有边与其相连
- {
- edge[ans]={u,v,w,0,head[u]};
- head[u]=ans++;
- edge[ans]={v,u,0,0,head[v]};
- head[v]=ans++;
- }
- else//如果有重边 则将流量合并
- if(w!=INF)
- edge[i].cap+=w;
- }
- void input()
- {
- int i,j,key;
- for(i=1;i<=m;i++)
- scanf("%d",&pig[i]);
- for(i=1;i<=n;i++)
- {
- scanf("%d",&a);
- while(a--)
- {
- scanf("%d",&key);
- map[key].push_back(i);//存储先后到第可以个猪圈的顾客编号
- }
- scanf("%d",&b[i]);
- }
- }
- void getmap()
- {
- int i,j;
- for(i=1;i<=m;i++)
- {
- int u=map[i][0];
- add(0,u,pig[i]);//超级源点连接第一个到i猪圈的顾客
- for(j=0;j<map[i].size()-1;j++)
- add(map[i][j],map[i][j+1],INF);//所有到i猪圈的顾客按照顺序连接
- }
- for(i=1;i<=n;i++)
- add(i,n+1,b[i]);//所有顾客连接汇点
- }
- int bfs(int beg,int end)
- {
- int i;
- memset(vis,0,sizeof(vis));
- memset(dis,-1,sizeof(dis));
- queue<int>q;
- while(!q.empty())
- q.pop();
- vis[beg]=1;
- dis[beg]=0;
- q.push(beg);
- while(!q.empty())
- {
- int u=q.front();
- q.pop();
- for(i=head[u];i!=-1;i=edge[i].next)//遍历所有的与u相连的边
- {
- node E=edge[i];
- if(!vis[E.to]&&E.cap>E.flow)//如果边未被访问且流量未满继续操作
- {
- dis[E.to]=dis[u]+1;//建立层次图
- vis[E.to]=1;//将当前点标记
- if(E.to==end)//如果当前点搜索到终点则停止搜索 返回1表示有从原点到达汇点的路径
- return 1;
- q.push(E.to);//将当前点入队
- }
- }
- }
- return 0;//返回0表示未找到从源点到汇点的路径
- }
- int dfs(int x,int a,int end)//把找到的这条边上的所有当前流量加上a(a是这条路径中的最小残余流量)
- {
- //int i;
- if(x==end||a==0)//如果搜索到终点或者最小的残余流量为0
- return a;
- int flow=0,f;
- for(int& i=cur[x];i!=-1;i=edge[i].next)//i从上次结束时的弧开始
- {
- node& E=edge[i];
- if(dis[E.to]==dis[x]+1&&(f=dfs(E.to,min(a,E.cap-E.flow),end))>0)//如果
- {//bfs中我们已经建立过层次图,现在如果 dis[E.to]==dis[x]+1表示是我们找到的路径
- //如果dfs>0表明最小的残余流量还有,我们要一直找到最小残余流量为0
- E.flow+=f;//正向边当前流量加上最小的残余流量
- edge[i^1].flow-=f;//反向边
- flow+=f;//总流量加上f
- a-=f;//最小可增流量减去f
- if(a==0)
- break;
- }
- }
- return flow;//所有边加上最小残余流量后的值
- }
- int Maxflow(int beg,int end)
- {
- int flow=0;
- while(bfs(beg,end))//存在最短路径
- {
- memcpy(cur,head,sizeof(head));//复制数组
- flow+=dfs(beg,INF,end);
- }
- return flow;//最大流量
- }
- int main()
- {
- while(scanf("%d%d",&m,&n)!=EOF)
- {
- init();
- input();
- getmap();
- printf("%d\n",Maxflow(0,n+1));
- }
- return 0;
- }
poj 1149 PIGS【最大流经典建图】的更多相关文章
- [poj] 1149 PIGS || 最大流经典题目
原题 题目大意 给你m个猪圈以及每个猪圈里原来有多少头猪,先后给你n个人,每个人能打开一些猪圈并且他们最多想买Ki头猪,在每一个人买完后能将打开的猪圈中的猪顺意分配在这次打开猪圈里,在下一个人来之前 ...
- poj--1149--PIGS(最大流经典建图)
PIGS Time Limit: 1000MS Memory Limit: 10000KB 64bit IO Format: %I64d & %I64u Submit Status D ...
- POJ 1149 - PIGS - [最大流构图]
Time Limit: 1000MS Memory Limit: 10000K Description Mirko works on a pig farm that consists of M loc ...
- POJ1149 最大流经典建图PIG
题意: 有一个人,他有m个猪圈,每个猪圈里都有一定数量的猪,但是他没有钥匙,然后依次来了n个顾客,每个顾客都有一些钥匙,还有他要卖猪的数量,每个顾客来的时候主人用顾客的钥匙打开相应的门,可 ...
- poj 1149 pigs ---- 最大流
题意以及分析:http://ycool.com/post/zhhrrm6#rule3 主要是建图,简化图,然后在套最大流的模板. #include <iostream> #include& ...
- POJ 2226 最小点覆盖(经典建图)
Muddy Fields Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8881 Accepted: 3300 Desc ...
- poj 1149 pigs(最大流)
题目大意:迈克在农场工作,农场有 m 个猪舍,每个猪舍有若干只猪,但是迈克不能打开任何一间猪舍.有 n 个顾客前来购买,每个顾客有最大的购买数量,每个顾客可以购买某些猪舍的猪,且顾客可以打开这些猪舍, ...
- hdoj--5093--Battle ships(二分图经典建图)
Battle ships Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Tot ...
- poj 1149 Pigs 网络流-最大流 建图的题目(明天更新)-已更新
题目大意:是有M个猪圈,N个顾客,顾客要买猪,神奇的是顾客有一些猪圈的钥匙而主人MIRKO却没有钥匙,多么神奇?顾客可以在打开的猪圈购买任意数量的猪,只要猪圈里有足够数量的猪.而且当顾客打开猪圈后mi ...
随机推荐
- Xcode 7.3.1的模拟器路径
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Core ...
- Shell编程练习
1.使用case语句 2.使用while....do....done语句 3.使用
- (重)POJ 3020Antenna Placement
http://poj.org/problem?id=3020 呃...这个题不是很会,所以找了大神的博客做了参考,说得很详细 http://blog.csdn.net/lyy289065406/art ...
- UVA 10801 Lift Hopping
算是一道需要动脑筋的最短路问题了,关键在于建图部分,对于n个电梯中每一个都要经过cnt个楼层,a[0],a[1],a[2],a[3],a[4],......a[cnt-1],那么对于任意两个楼层a[j ...
- 优化 Android 线程和后台任务开发
在 Android 开发中,你不应该做任何阻碍主线程的事情.但这究竟意味着什么呢?在这次海湾 Android 开发者大会讲座中,Ari Lacenski 认为对于长时间运行或潜在的复杂任务要特别小心. ...
- C语言动态内存管理
1-概述 动态存储管理的基本问题是:系统如何按请求分配内存,如何回收内存再利用.提出请求的用户可能是系统的一个作业,也可能是程序中的一个变量. 空闲块 未曾分配的地址连续的内存区称为“空闲块”. 占用 ...
- 【DataStructure In Python】Python模拟链表
最近一直在学习Python和Perl这两门语言,两者共同点很多,也有不多.希望通过这样的模拟练习可以让自己更熟悉语言,虽然很多时候觉得这样用Python或者Perl并没有体现这两者的真正价值. #! ...
- 函数 xdes_get_state
得到XDES Entry中状态 /**********************************************************************//** Gets the ...
- C#的同步和异步调用方法
同步和异步大家都明白什么意思,在这里不多介绍了. namespace ConsoleTest { class Program { static void Main(string[] args) { C ...
- BZOJ_1007_ [HNOI2008]_水平可见直线_(单调栈+凸包)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1007 给出一些直线,沿着y轴从上往下看,能看到多少条直线. 分析 由于直线相交,会遮挡住一些直 ...