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;
}