一道经典的构图题 。。
看了网上好多大牛的博文,最核心的,讲的最清楚的就是这个:点击打开链接 强烈推荐
下载下来慢慢研究。。。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <limits.h>
using namespace std;
const int inf=1e8-1;
const int N=1e5+5;
int n,m;
struct node
{
int u,v;
int flow;
} e[N];
int first[1000];
int next[N];
int sum[1000],flag[1000];
int k,nn;
int isap(int s,int t)
{
int num[1000],d[1000],cure[1000],pre[1000];
int cur,ans=0,u,tmp,neck;
memset(d,0,sizeof(d));
memset(num,0,sizeof(num));
memset(pre,-1,sizeof(pre));
for(int i=0; i<=nn; i++)
cure[i]=first[i];
num[0]=nn+1;
u=s;
while(d[t]<nn+1)
{
if(u==t)
{
cur=inf;
for(int i=s; i!=t; i=e[cure[i]].v)
if(cur>e[cure[i]].flow)
{
neck=i;
cur=e[cure[i]].flow;
}
for(int i=s; i!=t; i=e[cure[i]].v)
{
tmp=cure[i];
e[tmp].flow-=cur;
e[tmp^1].flow+=cur;
}
ans+=cur;
u=neck;
}
int i;
for(i=cure[u]; i!=-1; i=next[i])
if(e[i].flow&&d[u]==d[e[i].v]+1)
break;
if(i!=-1)
{
cure[u]=i;
pre[e[i].v]=u;
u=e[i].v;
}
else
{
if(0==--num[d[u]])
break;
cure[u]=first[u];
for(tmp=nn+1,i=first[u]; i!=-1; i=next[i])
if(e[i].flow)
tmp=min(tmp,d[e[i].v]);
d[u]=tmp+1;
++num[d[u]];
if(u!=s)
u=pre[u];
}
}
return ans;
}
inline void add(int u,int v,int w)
{
// printf("--%d %d %d\n",u,v,w);
e[k].u=u;
e[k].v=v;
e[k].flow=w;
next[k]=first[u];
first[u]=k++;
e[k].u=v;
e[k].v=u;
e[k].flow=0;
next[k]=first[v];
first[v]=k++;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(first,-1,sizeof(first));
memset(next,-1,sizeof(next));
memset(flag,-1,sizeof(flag));
k=0;
for(int i=1; i<=n; i++)
scanf("%d",&sum[i]);
nn=100+1;
for(int i=1; i<=m; i++)
{
int t,a;
scanf("%d",&t);
int res=0,w;
while(t--)
{
scanf("%d",&a);
if(flag[a]==-1)
{
res+=sum[a];
flag[a]=i;
}
else
add(flag[a],i,w=inf);
}
scanf("%d",&a);
add(i,nn,a);
if(res!=0)
add(0,i,res);
}
printf("%d\n",isap(0,nn));
}
}