其他分享
首页 > 其他分享> > bzoj 1280 Emmy卖猪pigs

bzoj 1280 Emmy卖猪pigs

作者:互联网

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;
}

标签:int,选到,卖猪,建图,pigs,maxn,顾客,Emmy
来源: https://www.cnblogs.com/chdy/p/12655555.html