LINK:1280: Emmy卖猪pigs
非常奇怪的最大流..建图还是一如既往的难想 感觉以前做过这个东西 所以也不难想出来辣.
考虑一头猪给谁都行都会增加贡献 但是不同位置的猪进行不同位置的挑选会带来更大的代价 这就是选位置即匹配问题.所以考虑最大流.
顾客一个一个来 就一个一个建图 为什么需要使用最大流 可能一个顾客选牛的时候选到一个点的牛 下一个顾客也可能选到 但是当前顾客有多种选择这个情况 所以需要最佳匹配来解决问题.
建图是关键 发现 对于当前的点的钥匙集合i来说 如果其之前的某个顾客的钥匙集合和其有交 那么就可以使用上一个顾客所有的牛了.
基于这个思想 我们将之前的顾客和现在的顾客直接连边就行了.
考虑正确性 发现这样做符合题目意思即符合时间的单向流动关系 且由于是最大流的缘故存在退流所以是正确的.
注意n m 别打反 就算打反了 数据范围别看反.
const int MAXN=110,maxn=1010;
int n,m,len=1,S,T,l,r;
int a[maxn],vis[maxn],q[maxn],g[maxn],cur[maxn];
int lin[maxn],ver[maxn*maxn<<1],nex[maxn*maxn<<1],e[maxn*maxn<<1];
inline void add(int x,int y,int z)
{
ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;
ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=0;
}
inline int bfs()
{
rep(1,T,i)vis[i]=0,cur[i]=lin[i];
l=r=0;vis[S]=1;q[++r]=S;
while(++l<=r)
{
int x=q[l];
go(x)
{
if(vis[tn]||!e[i])continue;
vis[tn]=vis[x]+1;
q[++r]=tn;
if(tn==T)return 1;
}
}
return 0;
}
inline int dinic(int x,int flow)
{
if(x==T)return flow;
int res=flow,k;
for(int i=cur[x];i&&res;i=nex[i])
{
cur[x]=i;
int tn=ver[i];
if(vis[tn]==vis[x]+1&&e[i])
{
k=dinic(tn,min(e[i],res));
if(!k){vis[tn]=0;continue;}
e[i]-=k;e[i^1]+=k;res-=k;
}
}
return flow-res;
}
int main()
{
freopen("1.in","r",stdin);
get(n);get(m);S=m+1;T=S+1;
rep(1,n,i)get(a[i]);
int sum=0,flow=0;
rep(1,m,i)
{
int get(x);
rep(1,x,j)
{
int get(y);
if(!g[y])add(S,i,a[y]);
else add(g[y],i,INF);
g[y]=i;
}
add(i,T,read());
while(bfs())while((flow=dinic(S,INF)))sum+=flow;
}
put(sum);return 0;
}