新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,欢迎批评指正
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 13677 | Accepted: 6044 |
Description
Input
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; }
文章结束给大家分享下程序员的一些笑话语录: 问:你觉得让你女朋友(或者任何一个女的)从你和李彦宏之间选一个,你觉得她会选谁?
答:因为李艳红这种败类,所以我没女友!
--------------------------------- 原创文章 By
数量和queue
---------------------------------