网络流好题:
这道题目的大意是这样的:
- 有 M 个猪圈(M ≤ 1000),每个猪圈里初始时有若干头猪。
- 一开始所有猪圈都是关闭的。
- 依次来了 N 个顾客(N ≤ 100),每个顾客分别会打开指定的几个猪圈,从中买若干头猪。
- 每个顾客分别都有他能够买的数量的上限。
- 每个顾客走后,他打开的那些猪圈中的猪,都可以被任意地调换到其它开着的猪圈里,然后所有猪圈重新关上。
由于这题的思路我没有想出来,而是学习了这篇博客,大家可以看一下。网上思路都差不多,这篇写得很好。
这题构图还是弄了我很久... 最终自己还是没能构出来,多学习多想想吧。
#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define MN 1111
#define INF 0x0FFFFFFF
#define CC(a,what) memset( a,what,sizeof(a) )
template<class T> inline void checkmin( T &a,T b ){ if(a>b||a==-1) a=b; }
using namespace std;int M,N,s,t;
int maze[MN][MN],cur[MN],pre[MN],dis[MN],gap[MN];void setG()
{int cap[1111],keyn,v;int pre[1111];CC(pre,0);CC(maze,0);s=0;t=N+1; for( int i=1;i<=M;i++ )scanf( "%d",&cap[i] );for( int i=1;i<=N;i++ ){scanf( "%d",&keyn );for( int j=1;j<=keyn;j++ ){scanf( "%d",&v );if( pre[v]==0 )maze[s][i]+=cap[v];elsemaze[pre[v]][i]=INF;pre[v]=i;}scanf( "%d",&maze[i][t] );}
}int sap()
{CC(cur,0),CC(dis,0),CC(gap,0);int u=pre[s]=s,maxflow=0,aug=-1;gap[0]=t+1;while( dis[s]<=t ){
loop:for( int v=cur[u];v<=t;v++ )if( maze[u][v]&&dis[u]==dis[v]+1 ){cur[u]=v;checkmin( aug,maze[u][v] );pre[v]=u;u=v;if( v==t ){maxflow+=aug;for( u=pre[u];v!=s;v=u,u=pre[u] ){maze[u][v]-=aug;maze[v][u]+=aug;}aug=-1;}goto loop;}int mind=t;for( int v=0;v<=t;v++ )if( maze[u][v]&&mind>dis[v] ){cur[u]=v;mind=dis[v];}if( --gap[dis[u]]==0 )break;gap[dis[u]=mind+1]++;u=pre[u]; }return maxflow;
}int main()
{while( scanf("%d%d",&M,&N)!=EOF ){setG();printf("%d\n",sap());}return 0;
}