Language: Default PIGS
Description Mirko works on a pig farm that consists of M locked pig-houses and Mirko can‘t unlock any pighouse because he doesn‘t have the keys. Customers come to the farm one after another. Each of them has keys to some pig-houses and wants to buy a certain number of 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 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 first line of input contains two integers M and N, 1 <= M <= 1000, 1 <= N <= 100, number of pighouses and number of customers. Pig houses are numbered from 1 to M and customers are numbered from 1 to N. 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 The first and only line of the output should contain the number of sold pigs. Sample Input 3 3 3 1 10 2 1 2 2 2 1 3 3 1 2 6 Sample Output 7 Source |
题意:m个猪圈n个顾客,告诉每个猪圈里猪的数量和顾客的需求量以及告诉顾客会到哪个猪圈买猪,问最多能卖出多少猪。
思路:本题的关键在于如何构造一个容量网络。
(1)将顾客看作除源点和汇点以外的点,并且另设两个节点作源点和汇点。
(2)源点和每一个猪圈的第一个顾客连边,权是开始时猪圈中猪的数量。
(3)若源点和某个节点之间有重边,则将权合并(因此源点流出的流量就是所有的猪圈能提供的猪的数量)
(4)顾客j紧跟在顾客i之后打开某个猪圈,则<i,j>的权是无穷大;这是因为,如果顾客j紧跟在i之后打开某个猪圈,那么迈克就有可能根据顾客j的需求将其他猪圈的猪调整到该猪圈,这样顾客j就能买到尽可能多的猪。
(5)每个顾客和汇点之间连边,变的权是顾客的购猪数量。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define maxn 1005 #define MAXN 2005 #define MAXM 1000000 #define mod 1000000009 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define FRE(i,a,b) for(i = a; i <= b; i++) #define FRL(i,a,b) for(i = a; i < b; i++) #define mem(t, v) memset ((t) , v, sizeof(t)) #define sf(n) scanf("%d", &n) #define sff(a,b) scanf("%d %d", &a, &b) #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c) #define pf printf #define DBG pf("Hi\n") typedef long long ll; using namespace std; int mp[111][111];//容量 int flow[111][111];//流量 int house[1005],last[1111]; int n,m,s,t; void MaxFlow() { int i,j,v; int pre[111]; int alpha[111];//可改进量 queue<int>Q; mem(flow,0); alpha[s]=INF; while (1) { FRE(i,0,110) pre[i]=-2; pre[s]=-1; Q.push(0); while (!Q.empty()) { v=Q.front(); Q.pop(); for (i=0;i<t+1;i++) { int p; if (pre[i]==-2&&(p=mp[v][i]-flow[v][i])!=0) { pre[i]=v; Q.push(i); alpha[i]=min(alpha[v],p); } } } if (pre[t]==-2) break; for (i=pre[t],j=t;i!=-1;j=i,i=pre[i]) { flow[i][j]+=alpha[t]; flow[j][i]-=alpha[t]; } } int ans=0; FRL(i,0,n+1) ans+=flow[i][t]; printf("%d\n",ans); return ; } int main() { int i,j; while (~sff(m,n)) { mem(last,0); mem(mp,0); FRE(i,1,m) sf(house[i]); int num=0,x; s=0,t=n+1; FRE(i,1,n) { sf(num); while (num--) { sf(x); if (last[x]==0) mp[s][i]+=house[x]; else mp[last[x]][i]=INF; last[x]=i; } sf(mp[i][t]); } MaxFlow(); } return 0; }
另附非递归dinic:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define maxn 1005 #define MAXN 2005 #define MAXM 1000000 #define mod 1000000009 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define FRE(i,a,b) for(i = a; i <= b; i++) #define FRL(i,a,b) for(i = a; i < b; i++) #define mem(t, v) memset ((t) , v, sizeof(t)) #define sf(n) scanf("%d", &n) #define sff(a,b) scanf("%d %d", &a, &b) #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c) #define pf printf #define DBG pf("Hi\n") typedef long long ll; using namespace std; struct Edge{ int to,next,cap,flow; }edge[MAXM]; int tol,n,m; int head[MAXN]; int house[1005]; int vis[1005]; int mp[111][111]; void init() { tol=2; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w,int rw=0) { edge[tol].to=v; edge[tol].cap=w; edge[tol].flow=0; edge[tol].next=head[u]; head[u]=tol++; edge[tol].to=u; edge[tol].cap=rw;//双向边时改成w edge[tol].flow=0; edge[tol].next=head[v]; head[v]=tol++; } int Q[MAXN]; int dep[MAXN],cur[MAXN],sta[MAXN]; bool bfs(int s,int t,int n) { int front=0,tail=0; memset(dep,-1,sizeof(dep[0])*(n+1)); dep[s]=0; Q[tail++]=s; while (front<tail) { int u=Q[front++]; for (int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if (edge[i].cap>edge[i].flow && dep[v]==-1) { dep[v]=dep[u]+1; if (v==t) return true; Q[tail++]=v; } } } return false; } int dinic(int s,int t,int n) { int maxflow=0; while (bfs(s,t,n)) { for (int i=0;i<n;i++) cur[i]=head[i]; int u=s,tail=0; while (cur[s]!=-1) { if (u==t) { int tp=INF; for (int i=tail-1;i>=0;i--) tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow); maxflow+=tp; for (int i=tail-1;i>=0;i--) { edge[sta[i]].flow+=tp; edge[sta[i]^1].flow-=tp; if (edge[sta[i]].cap-edge[sta[i]].flow==0) tail=i; } u=edge[sta[tail]^1].to; } else if (cur[u]!=-1 && edge[cur[u]].cap > edge[cur[u]].flow &&dep[u]+1==dep[edge[cur[u]].to]) { sta[tail++]=cur[u]; u=edge[cur[u]].to; } else { while (u!=s && cur[u]==-1) u=edge[sta[--tail]^1].to; cur[u]=edge[cur[u]].next; } } } return maxflow; } int main() { int i,j; while (~sff(m,n)) { init(); mem(vis,0); mem(mp,0); FRE(i,1,m) sf(house[i]); int num,s=0,t=n+1,x; FRE(i,1,n) { sf(num); while (num--) { sf(x); if (!vis[x]) mp[s][i]+=house[x]; else mp[vis[x]][i]=INF; vis[x]=i; } sf(mp[i][t]); } FRE(i,0,n+1) FRE(j,i,n+1) if (mp[i][j]!=0) addedge(i,j,mp[i][j]); int ans=dinic(s,t,n+2); printf("%d\n",ans); } return 0; }