本文纯属个人见解,是对前面学习的总结,如有描述不正确的地方还请高手指正~
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 13677 | Accepted: 6044 |
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
这题难点在于如何建图,如何懂得题目中的“if Mirko wants, he can redistribute the remaining pigs across the unlocked pig-houses.”也将成为建图的症结。
如果我们把每个主顾作为图中的点,则对于具有某个猪圈的钥匙的连续的两个主顾i和j,建一条边i->j。现在解释为何可以这样建边:比如说i具有猪圈1,2,3的钥匙,j具有猪圈1的钥匙,这样i,j同时具有3号猪圈的钥匙,按理说j只能打开1号猪圈,但i主顾购买猪后,Mirko是可以随便分配1,2,3中猪的数量的,所以j主顾实质上是可以得到1,2,3中的猪的。
因为猪圈有m个,所以我们可以加一个源点s,分离与n个主顾建边,鉴于下面的建边方式,s应与每个猪圈的第一个主顾建边,边容量为猪圈中猪的数量,若某个主顾同时为多个猪圈的第一个主顾,则数量相加。
每个主顾购买猪的数量是有上限的,所以我们应该引入一个汇点t,每个主顾与t建一条边,边容量为每个主顾须要购买的猪的数量。
#include <iostream>
#include<cstdio>
using namespace std;
const int MAXN=105;
const int INF=(1<<29);
int flow[MAXN][MAXN];//容量限制
int dalta[MAXN];//改变量
int pre[MAXN];
int flag[MAXN];//标号
int m,n;
int EK()
{
int i,maxflow=0;
int queue[MAXN],front,rear;
while(1)
{
front=rear=0;
for(i=1;i<=n+1;i++)
flag[i]=0;
flag[0]=1;
pre[0]=0;
dalta[0]=INF;
queue[rear++]=0;
while(front!=rear&&!flag[n+1])
{
int v=queue[front++];
for(i=1;i<=n+1;i++)
{
if(flag[i])
continue;
if(flow[v][i])
{
dalta[i]=min(dalta[v],flow[v][i]);
flag[i]=1;
pre[i]=v;
queue[rear++]=i;
}
}
}
if(!flag[n+1])
break;
maxflow+=dalta[n+1];
i=n+1;
while(i!=0)
{
flow[pre[i]][i]-=dalta[n+1];
flow[i][pre[i]]+=dalta[n+1];
i=pre[i];
}
}
return maxflow;
}
int main()
{
int i,j;
int pigs[1005];//每个猪圈中的猪的数量
int before[1005];//每个猪圈的前一个主顾
while(~scanf("%d%d",&m,&n))
{
for(i=0;i<=n+1;i++)
for(j=0;j<=n+1;j++)
flow[i][j]=0;
for(i=1;i<=m;i++)
{
scanf("%d",pigs+i);
before[i]=-1;
}
for(i=1;i<=n;i++)
{
int num;
scanf("%d",&num);
while(num--)
{
scanf("%d",&j);
if(before[j]==-1)
{
before[j]=i;
flow[0][i]+=pigs[j];
}
else
{
flow[before[j]][i]=INF;
before[j]=i;
}
}
scanf("%d",&j);
flow[i][n+1]=j;
}
printf("%d\n",EK());
}
return 0;
}
文章结束给大家分享下程序员的一些笑话语录: 打赌
飞机上,一位工程师和一位程序员坐在一起。程序员问工程师是否乐意和他一起玩一种有趣的游戏。工程师想睡觉,于是他很有礼貌地拒绝了,转身要睡觉。程序员坚持要玩并解释说这是一个非常有趣的游戏:"我问你一个问题,如果你不知道答案,我付你5美元。然后你问我一个问题,如果我答不上来,我付你5美元。"然而,工程师又很有礼貌地拒绝了,又要去睡觉。 程序员这时有些着急了,他说:"好吧,如果你不知道答案,你付5美元;如果我不知道答案,我付50美元。"果然,这的确起了作用,工程师答应了。程序员就问:"从地球到月球有多远?"工程师一句话也没有说,给了程序员5美元。 现在轮到工程师了,他问程序员:"什么上山时有三条腿,下山却有四条腿?"程序员很吃惊地看着工程师,拿出他的便携式电脑,查找里面的资料,过了半个小时,他叫醒工程师并给了工程师50美元。工程师很礼貌地接过钱又要去睡觉。程序员有些恼怒,问:"那么答案是什么呢?"工程师什么也没有说,掏出钱包,拿出5美元给程序员,转身就去睡觉了。
---------------------------------
原创文章 By
数量和queue
---------------------------------