BZOJ 2879: [Noi2012]美食节【动态加点网络流

80 篇文章 0 订阅
3 篇文章 0 订阅

动态加点的修车……

不幸把spfa的in_queue的tag打错了(aim打成了now)……跑这么慢一脸懵逼23333


#pragma GCC optimize(2)
#include<cstdio>
#include<algorithm>
#include<cstring>
#define INF 0x3f3f3f3f
#define MAXN 45
#define MAXM 105
#define MAXP 805
#define MAXE (MAXP+MAXP*MAXP+MAXM)
#define MAX_NODE (MAXP*MAXM+MAXP+2)
using namespace std;	int n,m,p;
int a[MAXN];
int time_[MAXP][MAXM];
struct t1{
	int to,frm,nxt,c,liu;
	t1(){}
	t1(int to,int frm,int nxt,int c,int liu):to(to),frm(frm),nxt(nxt),c(c),liu(liu){}
}edge[MAXE<<1];	int cnt_edge=1;
int fst[MAX_NODE];
void addedge(int x,int y,int c,int liu){
	edge[++cnt_edge]=t1(y,x,fst[x],c,liu);
	fst[x]=cnt_edge;
	edge[++cnt_edge]=t1(x,y,fst[y],-c,0);
	fst[y]=cnt_edge;
}

const int S=0,T=MAX_NODE-1;

int ans=0;
int dis[MAX_NODE];
int que[MAX_NODE],head,tail;
int in_que[MAX_NODE];
int Frm[MAX_NODE];
inline bool SPFA(int now){
	head=tail=0;
	que[tail++]=now;
	memset(dis,INF,sizeof dis);
	dis[now]=0;
	in_que[now]=1;
	while(head^tail){
		now=que[head++];
		if(head==MAX_NODE)	head=0;
		for(register int tmp=fst[now];tmp;tmp=edge[tmp].nxt){
			int aim=edge[tmp].to;
			if(edge[tmp].liu&&dis[aim]>dis[now]+edge[tmp].c){
				dis[aim]=dis[now]+edge[tmp].c;
				Frm[aim]=tmp;
				if(!in_que[aim])	que[tail++]=aim,in_que[aim]=1;
				if(tail==MAX_NODE)	tail=0;
			}
		}
		in_que[now]=0;
	}
	return dis[T]!=INF;
} 
inline void FLOW(){
	int a,b,rec=0,tmp;
	tmp=edge[Frm[T]].frm;
	a=tmp/p,b=tmp%p;
	if(!b)	--a,b=p;
	for(register int i=Frm[T];i;i=Frm[edge[i].frm]){
		rec+=edge[i].c;
		--edge[i].liu;
		++edge[i^1].liu;
	}
	ans+=rec;
	if(b==1)	return ;
	addedge(p*a+b-1,T,0,1);
	for(register int i=1,tmp=p*a+b-1,tmp1=p+2-b;i<=n;++i)
		addedge(i,tmp,tmp1*time_[i][a],1);
}
int read_x;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)	scanf("%d",a+i),p+=a[i];
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&time_[i][j]);
	
	for(register int i=1;i<=n;++i){
		addedge(S,i,0,a[i]);
		for(register int j=1;j<=m;++j)
			addedge(i,p*(j+1),time_[i][j],1);	
	}
	for(int i=1;i<=m;++i)	addedge(p*(i+1),T,0,1);
	
	while(SPFA(S))
		FLOW();
	printf("%d",ans);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值