BZOJ3876: [Ahoi2014]支线剧情

有下界最小费用可行流。建图可以优化,我没优化。

#include<algorithm>
#include<cstdio>
#include<cstring>
using std::min;
const int inf=1061109567;
const int N=305;
const int s=N-1;
const int t=N-2;
int n,z[N],q[N*N],c[N],d[N];
struct edge{
	int v,w,f;edge*s;
}e[N*N];
edge*a=e,*h[N];
void ins(int u,int v,int w,int f){
	edge s={v,w,f,h[u]};
	edge t={u,-w,0,h[v]};
	*(h[u]=a++)=s;
	*(h[v]=a++)=t;
}
bool spfa(){
	memset(c,63,sizeof c);
	memset(d,0,sizeof d);
	c[q[0]=t]=0;
	for(int a=0,b=0;a<=b;++a){
		int u=q[a];
		z[u]=0;
		for(edge*i=h[u];i;i=i->s)
			if(e[i-e^1].f&&c[u]-i->w<c[i->v]){
				c[i->v]=c[u]-i->w;
				d[i->v]=d[u]+1;
				if(!z[i->v]++)
					q[++b]=i->v;
			}
	}
	return c[s]!=inf;
}
int dfs(int u,int v){
	if(u==t)return v;
	int s=v;
	for(edge*i=h[u];i;i=i->s)
		if(c[i->v]==c[u]-i->w&&d[i->v]==d[u]-1&&i->f){
			int j=dfs(i->v,min(i->f,s));
			i->f-=j,s-=j;
			e[i-e^1].f+=j;
			if(!s)break;
		}
	if(s==v)c[u]=inf;
	return v-s;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		int j,v,w;
		scanf("%d",&j);
		ins(i,t,0,j);
		ins(i,1,0,inf);
		while(j--){
			scanf("%d%d",&v,&w);
			ins(s,v,w,1);
			ins(i,v,w,inf);
		}
	}
	int k=0;
	while(spfa())
		while(int j=dfs(s,inf))
			k+=j*c[s];
	printf("%d\n",k);
}
posted @ 2016-06-18 14:55  f321dd  阅读(329)  评论(0编辑  收藏  举报