标签:
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 18123 | Accepted: 8246 |
Description
Input
Output
Sample Input
3 3 3 1 10 2 1 2 2 2 1 3 3 1 2 6
Sample Output
7
题意:迈克在一个养猪场工作,养猪场有M个猪圈,每个猪圈都有一定数量的猪且都上了锁。由于迈克没有钥匙,所以他不能打开任何一个猪圈。要买猪的顾客一个接一个的来到养猪场,每个顾客都有一些猪圈的钥匙,而且他们要买一定数量的猪。具体销售过程:当每个顾客到来时,他将那些他拥有钥匙的猪圈全部打开;迈克从这些猪圈中挑出一些猪卖给他们;如果迈克愿意,他可以重新分配这些被打开的猪圈中的猪;当顾客离开时,猪圈再次被锁上。注意:猪圈可容纳的猪的数量没有限制。
现在我们知道每个猪圈猪的数目、每个顾客手中拥有的全部钥匙以及他们要买的猪的数目,问你迈克一天最多可以买出多少头猪。
构图方法:
1:设 0 为源点, n + 1为汇点
2:源点和每个猪圈的第 1 个顾客连边 ,边的权是开始时猪圈中猪的数目
3:若源点和某节点之间有重边,则将权合并(因此源点流出的流量就是所有的猪圈能提供的猪的数量)
4:顾客 j 紧跟在顾客 i 之后打开某个猪圈,则边< i, j > 的权是 INF,因为,如果顾客 j 紧跟在顾客 i 之后打开每个猪圈,那么迈就有可能根据顾客 j 的需要将其他猪圈中的猪调整到该猪圈,这样顾客 j 就能买到尽可能多的猪。
5:每个顾客和汇点之间连边,边的权值是顾客希望购买的猪的数目(因此汇点的流入量就是每个顾客说购买的猪的数目)
对题中给的数据构图:
1:有三个顾客,设为 v1, v2, v3。源点 为0,汇点为 n+1
2:第一个猪圈的第一位顾客是v1, 第二个猪圈的第一个顾客是v1,第三个猪圈的第一个顾客是v2,因此源点到v1 有重边,合并后,权值为 3 + 1 = 4,源点到v2有一条边,权值为10.
3:顾客v2 紧跟在v1后面打开第一个猪圈,顾客v3紧跟在v1后面打开第二个猪圈,因此v1 --> v2, v1-->v3都有边,权值为INF
4:每个顾客 v1, v2, v3到汇点n+1都有一条边,权值分别为 2,3,6.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#define maxn 2200
#define maxm 550000
#define INF 0x3f3f3f3f
using namespace std;
int dist[maxn], vis[maxn];
int head[maxn], cur[maxn], cnt;
vector<int>Fir[maxn];//
struct node{
int u, v, cap, flow, next;
};
node edge[maxm];
int pig_num[maxn];//每个猪圈中猪的数目
int buy_pig[maxn];//每个顾客想买猪的数目
int m, n; //m是猪圈的数目,n是顾客的数目
void init(){
cnt = 0;
memset(head, -1, sizeof(head));
for(int i = 1; i <= m; ++i)
Fir[i].clear();
}
void in_put(){
for(int i = 1; i <= m; ++i)
scanf("%d",&pig_num[i]);
for(int i = 1; i <= n; ++i){
int keysum;
scanf("%d", &keysum);
while(keysum--){
int k;
scanf("%d", &k);
Fir[k].push_back(i);
}
scanf("%d", &buy_pig[i]);
}
}
void add(int u, int v, int w){
int i;
for(i = head[u]; i != -1; i = edge[i].next){
if(edge[i].v == v)
break;
}
if(i == -1){ //没有重边
edge[cnt] = {u, v, w, 0, head[u]};
head[u] = cnt++;
edge[cnt] = {v, u, 0, 0, head[v]};
head[v] = cnt++;
}
else {
edge[i].cap += w;
}
}
void getmap(){
for(int i =1; i <= m; ++i){
add(0, Fir[i][0], pig_num[i]);
for(int j = 0; j < Fir[i].size() - 1; ++j){
add(Fir[i][j], Fir[i][j + 1], INF);
}
}
for(int i = 1; i <= n; ++i)
add(i, n + 1, buy_pig[i]);
}
bool BFS(int st ,int ed){
queue<int>q;
memset(dist, -1, sizeof(dist));
memset(vis, 0, sizeof(vis));
dist[st] = 0;
vis[st] = 1;
q.push(st);
while(!q.empty()){
int u = q.front();
q.pop();
for(int i = head[u]; i != -1; i = edge[i].next){
node E = edge[i];
if(!vis[E.v] && E.cap > E.flow){
vis[E.v] = 1;
dist[E.v] = dist[u] + 1;
if(E.v == ed) return true;
q.push(E.v);
}
}
}
return false;
}
int DFS(int x, int ed, int a){
if(x == ed || a == 0)
return a;
int flow = 0, f;
for(int &i = cur[x]; i != -1; i = edge[i].next){
node &E = edge[i];
if(dist[E.v] == dist[x] + 1 && (f = DFS(E.v, ed, min(a, E.cap - E.flow)))> 0){
E.flow += f;
edge[i ^ 1].flow -= f;
a -= f;
flow += f;
if(a == 0) break;
}
}
return flow;
}
int maxflow(int st ,int ed){
int flowsum = 0;
while(BFS(st, ed)){
memcpy(cur, head, sizeof(head));
flowsum += DFS(st, ed, INF);
}
return flowsum;
}
int main(){
while(scanf("%d%d", &m, &n) != EOF){
init();
in_put();
getmap();
printf("%d\n", maxflow(0, n + 1));
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
POJ 1149--PIGS 【最大流 && 处理重边 && 经典建模】
标签:
原文地址:http://blog.csdn.net/hpuhjh/article/details/47295803