题目链接传送门
@xuxiayang
整个机房的 A C AC AC 都因他而起。
@liuzihan
他造就了我的 A C AC AC 。
步入正题:
这道题其实就是让你
先跑一遍
S
P
F
A
SPFA
SPFA
用来求出最低的买入水晶球的价格
再将图反置,从后往前
再跑一遍
S
P
F
A
SPFA
SPFA
用来求出最高的卖出水晶球的价格
最后从2到n
求出一个最大的最高价值减去最小价值的值
提几个要点:
1. 领接表的建立
这次领接表的建立有点不一样
需要分两种情况来分别建立
void ljb1(int x,int y) // NO。1
{
e1[++tot1].x=x;
e1[tot1].to=y;
e1[tot1].next=hd1[x];
hd1[x]=tot1;
}
void ljb2(int x,int y) // NO.2
{
e2[++tot2].x=x;
e2[tot2].to=y;
e2[tot2].next=hd2[x];
hd2[x]=tot2;
}
2. 反置
反置的意思:
就是把图中所有的线路全部反过来
如下图:
这与第一个要点相关联,
我们需要判断
z
z
z 的类型
是
1
1
1
就单向并反置,
是
2
2
2
就双向并反置。
知道了这些东西: 我们就能做出来啦!
(搞了一个晚上)
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,m,w[100100];
int dis1[1000100],dis2[1000100];
int dl1[1000100];
int v1[1010001];
int tot1,tot2,hd1[10001000],hd2[10001000];
int ans;
struct node1
{
int x,to,next;
}e1[10000010];
struct node2
{
int x,to,next;
}e2[1000100];
void ljb1(int x,int y)
{
e1[++tot1].x=x;
e1[tot1].to=y;
e1[tot1].next=hd1[x];
hd1[x]=tot1;
}
void ljb2(int x,int y)
{
e2[++tot2].x=x;
e2[tot2].to=y;
e2[tot2].next=hd2[x];
hd2[x]=tot2;
}
void spfa1(int x)
{
memset(dis1,0x3f,sizeof(dis1));
int head=0,tail=1;
dis1[x]=w[x],v1[x]=1,dl1[1]=x;
while(head!=tail)
{
head=head%100010+1;
int x1=dl1[head];
for(int i=hd1[x1];i;i=e1[i].next)
{
if(min(w[e1[i].to],dis1[x1])<dis1[e1[i].to])
{
dis1[e1[i].to]=min(w[e1[i].to],dis1[x1]);
if(v1[e1[i].to]==0)
{
tail=tail+1;
v1[e1[i].to]=1;
dl1[tail]=e1[i].to;
}
}
}
v1[x1]=0;
}
}
void spfa2(int x)
{
memset(v1,0,sizeof(v1));
int head=0,tail=1;
dis2[x]=w[x],v1[x]=1,dl1[1]=x;
while(head!=tail)
{
head=head%1000100+1;
int x1=dl1[head];
for(int i=hd2[x1];i;i=e2[i].next)
{
if(max(w[e2[i].to],dis2[x1])>dis2[e2[i].to])
{
dis2[e2[i].to]=max(w[e2[i].to],dis2[x1]);
if(v1[e2[i].to]==0)
{
tail=tail+1;
v1[e2[i].to]=1;
dl1[tail]=e2[i].to;
}
}
}
v1[x1]=0;
}
}
int main()
{
cin>>n>>m;
for(int i=1; i<=n; i++)
cin>>w[i];
for(int i=1; i<=m; i++)
{
int x,y,z;
cin>>x>>y>>z;
if(z==1)
{
ljb1(x,y);
ljb2(y,x);
}
else if(z==2)
{
ljb1(x,y);
ljb1(y,x);
ljb2(y,x);
ljb2(x,y);
}
}
spfa1(1);
spfa2(n);
ans=0;
for(int i=2; i<n; i++)
ans=max(ans,dis2[i]-dis1[i]);
cout<<ans;
return 0;
}