P1073 [NOIP2009 提高组] 最优贸易做题笔记

思路是建一个反图,在原图上从点 \(1\) 开始跑一遍 \(SPFA\),算出点 \(1\) 到点 \(x\) 的最短路径上的价格最小值 \(e_x\);再在反图上从点 \(n\) 开始跑一遍 \(SPFA\),算出点 \(n\) 到点 \(1\) 的最短路径上的价格最大值 \(f_x\),答案为 \(\max(f_x - e_x) (1 \le x \le n)\)

#include <bits/stdc++.h>
  using namespace std;
int n,m,k,l,u,v,w,p[100005],c[100005],d[100005],e[100005],f[100005],ans,i;
bool o[100005];
queue<int>q;
struct xy{
	int x,y,z;
}a[1000005],b[1000005];
void Add()
{
	a[++k].x=c[u];
	c[u]=k;
	a[k].y=v;
	// a[k].z=o[v];
	b[++l].x=d[v];
	d[v]=l;
	b[l].y=u;
	// a[k].z=o[v];
}
void DAdd()
{
	a[++k].x=c[u];
	c[u]=k;
	a[k].y=v;
	// a[k].z=o[v];
	a[++k].x=c[v];
	c[v]=k;
	a[k].y=u;
	// a[k].z=o[u];
	b[++l].x=d[u];
	d[u]=l;
	b[l].y=v;
	// b[k].z=o[v];
	b[++l].x=d[v];
	d[v]=l;
	b[l].y=u;
	// b[k].z=o[u];
}
void spfa()
{
	int j,t;
	memset(o,0,sizeof(o));
	memset(e,0x7f,sizeof(e));
	q.push(1);
	o[1]=1;
	while (!q.empty())
	{
		t=q.front();
		q.pop();
		o[t]=0;
		for (j=c[t];j;j=a[j].x)
		{
			if (e[a[j].y]>min(e[t],p[a[j].y]))
			{
				e[a[j].y]=min(e[t],p[a[j].y]);
				if (!o[a[j].y])
				{
					o[a[j].y]=1;
					q.push(a[j].y);
				}
			}
		}
	}
}
void Fspfa()
{
	int j,t;
	memset(o,0,sizeof(o));
	q.push(n);
	o[n]=1;
	while (!q.empty())
	{
		t=q.front();
		q.pop();
		o[t]=0;
		for (j=d[t];j;j=b[j].x)
		{
			if (f[b[j].y]<max(f[t],p[b[j].y]))
			{
				f[b[j].y]=max(f[t],p[b[j].y]);
				if (!o[b[j].y])
				{
					o[b[j].y]=1;
					q.push(b[j].y);
				}
			}
		}
	}
}
int main()
{
	ios::sync_with_stdio(0); cin.tie(nullptr);
	cin>>n>>m;
	for (i=1;i<=n;i++)
	{
		cin>>p[i];
	}
	for (i=1;i<=m;i++)
	{
		cin>>u>>v>>w;
		if (w==1) Add();
		else DAdd();
	}
	spfa();
	Fspfa();
	for (i=1;i<=n;i++)
	{
		ans=max(ans,f[i]-e[i]);
	}
	cout<<ans<<endl;
	return 0;
}
posted @ 2022-06-13 07:32  Jason142  阅读(24)  评论(0编辑  收藏  举报