关于此题的费用流解法优化
查看原帖
关于此题的费用流解法优化
822239
ncwzdlsd楼主2023/10/29 22:09

rt。用 SPFA+Dinic 求费用流,当前弧优化、多路增广还有 SPFA 的 SLF、LLL 优化都用了,就是卡不过最后一个点。看题解发现费用流写得好一点也可以通过此题,求助有没有什么其他的优化方式,有没有人能帮忙优化一下,非常感谢/kel。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxm=4e6+5,maxn=5e5+5;
int head[maxn],cnt=1,n,m,s,t,r[maxn],now[maxn],m1,m2,c1,c2,p,tot,ss;
struct edge{ll to,nxt;ll c,w;}e[maxm];
bool vis[maxn],vv[maxn];
ll dis[maxn],minc;

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}

inline void add(int x,int y,ll z,ll q){e[++cnt]={y,head[x],z,q},head[x]=cnt;}

inline bool spfa()
{
	deque<int> q;
	int i;
	for(i=0;i<=t;++i) dis[i]=1e18;
	memset(vis,0,(t+1)*sizeof(bool));
	q.push_back(0),vis[0]=1,dis[0]=0,tot=1;
	while(!q.empty())
	{
		int x=q.front();vis[x]=0;
		while(tot*dis[x]>ss) q.pop_back(),q.push_back(x),x=q.front();
		q.pop_front(),tot--,ss-=dis[x];
		for(i=head[x];i;i=e[i].nxt)
			if(e[i].c>0&&dis[e[i].to]>dis[x]+e[i].w)
			{
				dis[e[i].to]=dis[x]+e[i].w;
				if(!vis[e[i].to])
					(dis[e[i].to]<=dis[q.front()])?q.push_front(e[i].to):q.push_back(e[i].to),vis[e[i].to]=1,ss+=dis[e[i].to],tot++;
			}
	}
	return dis[t]!=1e18;
}

inline ll dfs(int x,ll mxf)
{
	if(x==t) return mxf;
	ll sum=0;vv[x]=1;
	int i;
	for(i=now[x];i;i=e[i].nxt)
	{
		now[x]=i;
		if(!vv[e[i].to]&&e[i].c>0&&dis[e[i].to]==dis[x]+e[i].w)
		{
			ll ff=dfs(e[i].to,min(mxf-sum,e[i].c));
			if(ff) e[i].c-=ff,e[i^1].c+=ff,sum+=ff,minc+=ff*e[i].w;
		}
		if(sum==mxf) break;
	}
	vv[x]=0;
	return sum;
}

void dinic(){while(spfa()) memcpy(now,head,(t+1)*sizeof(int)),dfs(0,1e18);}

signed main()
{
	// ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n>>m1>>m2>>c1>>c2>>p;
	t=2*n+1;
	int i;
	for(i=1;i<=n;++i) r[i]=read(),add(0,i,r[i],0),add(i,0,0,0),add(i+n,t,r[i],0),add(t,i+n,0,0);
	for(i=1;i<=n;++i)
	{
		add(0,i+n,1e18,p),add(i+n,0,0,-p);
		if(i+1<=n) add(i,i+1,1e18,0),add(i+1,i,0,0);
		if(i+m1<=n) add(i,i+m1+n,1e18,c1),add(i+m1+n,i,0,-c1);
		if(i+m2<=n) add(i,i+m2+n,1e18,c2),add(i+m2+n,i,0,-c2);
	}
	dinic();
	cout<<minc;
	return 0;
}
2023/10/29 22:09
加载中...