bzoj3876: [Ahoi2014]支线剧情 费用流

Posted f321dd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3876: [Ahoi2014]支线剧情 费用流相关的知识,希望对你有一定的参考价值。

按照有下界网络流求可行流的方法求出最小费用可行流。

写的费用流多路增广,比裸ek快一点。

其实这题有很优越的建图方法,然而并不会。

#include<bits/stdc++.h>
#define N 309
using namespace std;
int cost,n;
int d[N],s=N-1,t=N-2;
bool p[N];
const int inf=1061109567;
struct edge{
	edge* s;
	int v,w,cp;
}e[N*N],*back(e),*h[N];
void add(
int u,int v,int w,int cp){
	h[u]=&(*back++
	=(edge){h[u],v,w,cp});
	h[v]=&(*back++
	=(edge){h[v],u,-w,0});
}
bool spfa(){
	static bool a[N];
	queue<int> q;
	q.push(s);
	memset(d,63,sizeof d);
	d[s]=0;
	while(q.size()){
		int u=q.front();
		q.pop();
		a[u]=0;
		for(edge* i=h[u];i;i=i->s)
			if(i->cp
			&&d[i->v]>d[u]+i->w){
				d[i->v]=d[u]+i->w;
				if(!a[i->v]){
					a[i->v]=1;
					q.push(i->v);
				}
			}
	}
	return d[t]!=inf;
}
int dfs(int u,int a){
	int s=0;
	p[u]=1;
	for(edge* i=h[u];s!=a
	&&i;i=i->s){
		if(!i->cp||p[i->v]
		||d[i->v]!=d[u]+i->w)
			continue;
		int j=min(a-s,i->cp);
		if(i->v==t
		||(j=dfs(i->v,j))){
			s+=j;
			cost+=i->w*j;
			i->cp-=j;
			e[i-e^1].cp+=j;
		}
	}
	return s;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		int j,v,w;
		scanf("%d",&j);
		add(i,t,0,j);
		add(i,1,0,inf);
		while(j--){
			scanf("%d%d",&v,&w);
			add(s,v,w,1);
			add(i,v,w,inf);
		}
	}
	while(spfa()){
		memset(p,0,sizeof p);
		dfs(s,inf);
	}
	printf("%d\n",cost);
}

  

以上是关于bzoj3876: [Ahoi2014]支线剧情 费用流的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj3876 [Ahoi2014]支线剧情

3876: [Ahoi2014&Jsoi2014]支线剧情

网络流BZOJ 3876 [Ahoi2014]支线剧情

bzoj 3876: [Ahoi2014]支线剧情

BZOJ 3876 AHOI2014 支线剧情

bzoj3876: [Ahoi2014]支线剧情 费用流