建图详细解释请看转发的博文
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; #define MAXN 200 #define MAXE 5000 #define INF 0xfffff int ne,nv,tmp,s,t,index; struct Edge{ int next,pair,v; int cap,fLow; }edge[MAXE]; int g[1010][110]; int net[MAXN]; int ISAP() { int numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN]; int cur_fLow,max_fLow; int u,tmp,neck,i; memset(dist,0,sizeof(dist)); memset(numb,0,sizeof(numb)); memset(pre,-1,sizeof(pre)); for(i = 1 ; i <= nv ; ++i) curedge[i] = net[i]; numb[nv] = nv; max_fLow = 0; u = s; while(dist[s] < nv) { if(u == t) { cur_fLow = INF+1; for(i = s; i != t;i = edge[curedge[i]].v) { if(cur_fLow > edge[curedge[i]].cap) { neck = i; cur_fLow = edge[curedge[i]].cap; } } for(i = s; i != t; i = edge[curedge[i]].v) { tmp = curedge[i]; edge[tmp].cap -= cur_fLow; edge[tmp].fLow += cur_fLow; tmp = edge[tmp].pair; edge[tmp].cap += cur_fLow; edge[tmp].fLow -= cur_fLow; } max_fLow += cur_fLow; u = neck; } for(i = curedge[u]; i != -1; i = edge[i].next) if(edge[i].cap > 0 && dist[u] == dist[edge[i].v]+1) break; if(i != -1) { curedge[u] = i; pre[edge[i].v] = u; u = edge[i].v; }else{ if(0 == --numb[dist[u]]) break; curedge[u] = net[u]; for(tmp = nv,i = net[u]; i != -1; i = edge[i].next) if(edge[i].cap > 0) tmp = tmp<dist[edge[i].v]?tmp:dist[edge[i].v]; dist[u] = tmp + 1; ++numb[dist[u]]; if(u != s) u = pre[u]; } } return max_fLow; } void addedge(int u,int v,int f) { edge[index].next = net[u]; edge[index].v = v; edge[index].cap = f; edge[index].fLow = 0; edge[index].pair = index+1; net[u] = index++; edge[index].next = net[v]; edge[index].v = u; edge[index].cap = 0; edge[index].fLow = 0; edge[index].pair = index-1; net[v] = index++; } int main() { int i,j,m,n; int sum; int pig[1010]; int vis[1010]; while(~scanf("%d%d",&m,&n)) { memset(pig,0,sizeof(pig)); sum=0;index=0; s = 0; t = n+1;nv=t+1; memset(g,0,sizeof(g)); memset(net,-1,sizeof(net)); memset(vis,0,sizeof(vis)); for(i=1;i<=m;i++) { scanf("%d",&pig[i]); } for(i=1;i<=n;i++) { int k; scanf("%d",&k); for(j=1;j<=k;j++) { int temp; scanf("%d",&temp); g[temp][i]=1; if(vis[temp]==0) { addedge(s,i,pig[temp]); vis[temp]=1; } } int temp; scanf("%d",&temp); addedge(i,t,temp); } for(i=1;i<=m;i++) { int first=1; int prepig; for(j=1;j<=n;j++) { if(first) { if(g[i][j]){first=0;prepig=j;} } else { if(g[i][j]){addedge(prepig,j,INF);prepig=j;} } } } int ans=ISAP(); printf("%d\n",ans); } return 0; }