【题解】洛谷P1073 最优贸易(spfa 分层图状态转移)

https://www.luogu.org/blog/user15019/solution-p1073

这个题使用分层图状态转移来解决的思想如上,不过个人觉得可能那种建图方式有些繁琐,所以出了个写了个简化版本。

我们没有必要把1-n个城市的买入卖出收益存入数组里,在循环里设一个临时变量,然后建图时,将i和i+n相连赋权值,而不用按照第一层的图在第二层找到对应的点,只用竖直下去就可以,这样在跑spfa时会方便许多。注意设一个最终的终点为3*n+1,spfa的数值不要写错,应当是3*n+1就行了

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn=100010;
const int maxm=500050;
int head[maxn*3],nnext[maxm*3*2],to[maxm*3*2],length[maxn*3*2];
bool b[maxn*3];
int team[maxn*3],dis[maxn*3],s=0,t=0;
int n,m,tot,sn;
void add(int x,int y,int l)
{
	tot++;
	nnext[tot]=head[x];
	head[x]=tot;
	to[tot]=y;
	length[tot]=l;
}
void spfa()
{
	for(int i=1;i<=sn;i++)
	{
		dis[i]=-1e9;
	}dis[1]=0;
	
	team[t]=1;
	t++;
	b[1]=true;
	
	while(s!=t)
	{
		int now=team[s];
		s++;
		s%=sn;
		b[now]=false;
		for(int i=head[now];i;i=nnext[i])
		{
			int y=to[i];
			if(dis[y]<dis[now]+length[i])
			{
				dis[y]=dis[now]+length[i];
				if(b[y]==false)
				{
					team[t]=y;
					t++;
					t%=sn;
					b[y]=true;
				}
			}
		}
	}
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) 
	{
		int tmp;
		cin>>tmp;
		add(i,i+n,-tmp);
		add(i+n,i+2*n,tmp); 
	}
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		cin>>x>>y>>z;
		add(x,y,0);
		x+=n,y+=n;add(x,y,0);
		x+=n,y+=n;add(x,y,0);
		if(z==2)
		{
			add(y,x,0);
			x-=n,y-=n;add(y,x,0);
			x-=n,y-=n;add(y,x,0);
		}
	}
	sn=3*n+1;
	add(n,3*n+1,0);
	add(3*n,3*n+1,0);
	spfa();
	cout<<dis[sn]<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/rem_inory/article/details/81138457