标签:
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