题意:n个人买猪,有m个猪圈,每个人可以买多个猪圈的k头猪,买完之后这些猪圈的猪就可以走动了,否则每一个猪圈的猪只能呆在各自的猪圈里。
问最多可以卖出几头猪。
思路:http://imlazy.ycool.com/post.2059102.html
第一道网络流,拿来验证yy的模版。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
const int M = 20009;
const int N = 209;
const int INF = 0x7ffffff;
int g[N][N],gap[N],dist[N],pre[N],cur[N];
///s源,t汇,所有点1-n
int n,m,s,t;
int calc(){
int maxflow=0,aug=INF,u,v;
memset(gap,0,sizeof(gap));
memset(dist,0,sizeof(dist));
for(int i=0; i<=n; i++)cur[i]=1;
u=pre[s]=s;
gap[0]=n;
while(dist[s]<=n){
loop:
for(v=cur[u]; v<=n; v++)
if(g[u][v]>0 &&dist[u]==dist[v]+1)
{
cur[u]=v;
aug=min(aug,g[u][v]);
pre[v]=u;
u=v;
if(v==t){
maxflow+=aug;
for(u=pre[u];v!=s;v=u,u=pre[u]){
g[u][v]-=aug;
g[v][u]+=aug;
}
aug=INF;
}
goto loop;
}
int mind=n;
for(v=1; v<=n; v++)
if(g[u][v]>0 &&mind>dist[v]){
mind=dist[v];
cur[u]=v;
}
if(--gap[dist[u]]<=0)break;
gap[dist[u]=mind+1]++;
u=pre[u];
}
return maxflow;
}
int pig[N],re[N];
void init()
{
memset(re,0,sizeof(re));
memset(g,0,sizeof(g));
}
int main()
{
freopen("in.txt","r",stdin);
while(~scanf("%d%d",&m,&n))
{
init();
n++;
s=1,t=n+1;
for(int i=1; i<=m; i++) scanf("%d",&pig[i]);
for(int i=2; i<=n; i++)
{
int a,b;
scanf("%d",&a);
for(int j=0; j<a; j++)
{
scanf("%d",&b);
if(re[b]==0)
g[s][i]+=pig[b];
else
g[re[b]][i]=INF;
if(!re[b])
re[b]=i;
}
scanf("%d",&b);
g[i][t]+=b;
}n++;
printf("%d\n",calc());
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
const int N = 209;
const int M = 2009;
const int INF = 0x3f3f3f3f;
struct LT{
int f,t,nex,c;
}L[M*4];
int F[N],cnt;
void add(int f,int t,int c){
L[cnt].c = c;L[cnt].f = f;
L[cnt].t = t;L[cnt].nex = F[f];
F[f] = cnt++;
L[cnt].c = 0;L[cnt].f = t;
L[cnt].t = f;L[cnt].nex = F[t];
F[t] = cnt++;
}
int dep[N],num[N],pre[N],cur[N],que[N];
///s源 t汇 所有点1-n
int s,t,n,p;
void bfs(){
int front=0, rear=0;
int x,i,v;
for(i=1;i<=n;i++)
dep[i]=INF;
dep[t]=0;
memset(num,0,sizeof(num));
num[dep[t]]++;
que[rear++]=t;
while(front<rear){
x=que[front++];//cout<<x<<endl;
for(i=F[x]; i!=-1; i=L[i].nex){
v=L[i].t;
if(dep[v]==INF &&L[i^1].c){
dep[v]=dep[x]+1;
num[dep[v]]++;
que[rear++]=v;
}
}
}
}
int find(int x){
for(int i=F[x]; i!=-1; i=L[i].nex)
if(L[i].c &&dep[L[i].t]+1==dep[x]){
cur[L[i].t]=i;
return L[i].t;
}
return -1;
}
int relable(int i){
int min=INF;
for(int j=F[i]; j!=-1; j=L[j].nex)
if(L[j].c&&dep[L[j].t]+1<min){
min=dep[L[j].t]+1;
}
return min==INF?n:min;
}
int maxflow(){
bfs();
int flow=0,i=s,j,delta;
memset(pre,-1,sizeof(pre));
while(dep[s]<n){
j=find(i);
if(j>0){
pre[j]=i;
i=j;
if(i==t){
delta=INF;
for(i=t; i!=s; i=pre[i])
if(L[cur[i]].c<delta)
delta=L[cur[i]].c;
for(i=t; i!=s; i=pre[i]){
L[cur[i]].c-=delta;
L[cur[i]^1].c+=delta;
}
flow+=delta;
}
}else{
int x=relable(i);
num[x]++;
num[dep[i]]--;
if(num[dep[i]]==0)return flow;
dep[i]=x;
if(i!=s)i=pre[i];
}
}
return flow;
}
int pig[N],re[N];
void init()
{
cnt = 0;
memset(F,-1,sizeof(F));
memset(re,0,sizeof(re));
}
int main()
{
freopen("in.txt","r",stdin);
int m;
while(~scanf("%d%d",&m,&n))
{
init();
n++;
s=1,t=n+1;
for(int i=1; i<=m; i++) scanf("%d",&pig[i]);
for(int i=2; i<=n; i++)
{
int a,b;
scanf("%d",&a);
for(int j=0; j<a; j++)
{
scanf("%d",&b);
if(re[b]==0)
add(s,i,pig[b]);
else
add(re[b],i,INF);
if(!re[b])
re[b]=i;
}
scanf("%d",&b);
add(i,t,b);
}n++;
printf("%d\n",maxflow());
}
return 0;
}