原题链接
P1073
题目类型:
普
及
+
/
提
高
{\color{green}{普及+/提高}}
普及+/提高
AC记录:Accepted
题目大意
C国有
n
n
n个大城市和
m
m
m条道路。这
m
m
m条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为
1
1
1条。
C
C
C国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同。但是,同一种商品在同一个城市的买入价和卖出价始终是相同的。
商人阿龙来到
C
C
C国旅游,决定在旅游的同时,利用商品在不同城市中的差价赚回一点旅费。设
C
C
C国
n
n
n个城市的标号从
1
⋯
n
1\cdots n
1⋯n,阿龙决定从
1
1
1号城市出发,并最终在
n
n
n号城市结束自己的旅行。在旅游的过程中,任何城市可以重复经过多次,但不要求经过所有
n
n
n个城市。阿龙通过这样的贸易方式赚取旅费:他会选择一个经过的城市买入他最喜欢的商品――水晶球,并在之后经过的另一个城市卖出这个水晶球,用赚取的差价当做旅费。由于阿龙主要是来
C
C
C国旅游,他决定这个贸易只进行最多一次,当然,在赚不到差价的情况下他就无需进行贸易。
现在给出
n
n
n个城市的水晶球价格,
m
m
m条道路的信息,请你告诉阿龙,他最多能赚取多少旅费。
输入格式
第一行包含
2
2
2个正整数
n
n
n和
m
m
m,中间用一个空格隔开,分别表示城市的数目和道路的数目。
第二行
n
n
n个正整数,每两个整数之间用一个空格隔开,按标号顺序分别表示这
n
n
n个城市的商品价格。
接下来
m
m
m行,每行有
3
3
3个正整数
x
,
y
,
z
x,y,z
x,y,z,每两个整数之间用一个空格隔开。如果
z
=
1
z=1
z=1,表示这条道路是城市
x
x
x到城市
y
y
y之间的单向道路;如果
z
=
2
z=2
z=2,表示这条道路为城市
x
x
x和城市
y
y
y之间的双向道路。
输出格式
一个整数,表示最多能赚取的旅费。如果没有进行贸易,则输出
0
0
0。
S
a
m
p
l
e
\mathbf{Sample}
Sample
I
n
p
u
t
\mathbf{Input}
Input
5 5
4 3 5 6 1
1 2 1
1 4 1
2 3 2
3 5 1
4 5 2
S a m p l e \mathbf{Sample} Sample O u t p u t \mathbf{Output} Output
5
H
i
n
t
&
E
x
p
l
a
i
n
\mathbf{Hint\&Explain}
Hint&Explain
样例如图所示。
阿龙可以选择如下一条线路1->4->5->4->5
,并在第
1
1
1次到达
5
5
5号城市时以
1
1
1的价格买入水晶球,在第
2
2
2次到达
4
4
4号城市时以
6
6
6的价格卖出水晶球,赚取的旅费数为
5
5
5。
数据范围
输入数据保证
1
1
1号城市可以到达
n
n
n号城市。
对于
10
%
10\%
10%的数据,
1
≤
n
≤
6
1≤n≤6
1≤n≤6。
对于
30
%
30\%
30%的数据,
1
≤
n
≤
100
1≤n≤100
1≤n≤100。
对于
50
%
50\%
50%的数据,不存在一条旅游路线,可以从一个城市出发,再回到这个城市。
对于
100
%
100\%
100%的数据,
1
≤
n
≤
100000
,
1
≤
m
≤
500000
,
1
≤
x
,
y
≤
n
,
1
≤
z
≤
2
,
1
≤
各
城
市
水
晶
球
价
格
≤
100
。
1≤n≤100000,1≤m≤500000,1≤x,y≤n,1≤z≤2,1≤各城市水晶球价格≤100。
1≤n≤100000,1≤m≤500000,1≤x,y≤n,1≤z≤2,1≤各城市水晶球价格≤100。
解题思路
类似于51nod 2650 最短缩减路径的解法,我们这一次不是建一个两层的图,而是建一个三层的图!
第一层:原图,第二层:买了一个水晶球,第三层:卖掉了水晶球。
虽然有点乱,但是我尽量画的立体一点。
同层的点连起来的权值为
0
0
0,例如从
C
1
C_1
C1连到
A
1
A_1
A1的权值就是
0
0
0。
第一层连到第二层的线的权值为负,设从第一层的
α
\alpha
α点连到第二层的
β
\beta
β点,第
i
i
i个点的权值为
w
i
w_i
wi,则这条线的权值就是
−
w
α
-w_\alpha
−wα,例如从
C
1
C_1
C1连到
A
2
A_2
A2的权值就是
−
w
C
1
-w_{C_1}
−wC1。
第一层连到第二层的线的权值为正,设从第二层的
α
\alpha
α点连到第三层的
β
\beta
β点,第
i
i
i个点的权值为
w
i
w_i
wi,则这条线的权值就是
w
α
w_\alpha
wα,例如从
C
2
C_2
C2连到
A
3
A_3
A3的权值就是
w
C
1
w_{C_1}
wC1。
然后就可以做
S
p
f
a
Spfa
Spfa了。
由于他可以不买东西,所以要把答案设为第
n
n
n个点和第
3
n
3n
3n个点之间的最大值。
最后,祝大家早日
上代码
#include<bits/stdc++.h>
using namespace std;
vector<pair<int,int> > road[300010];
queue<int> q;
bool vis[300010];
int dist[300010];
int a[300010];
int n,m;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
for(int i=1; i<=n; i++)
cin>>a[i];
for(int i=1; i<=m; i++)
{
int x,y,z;
cin>>x>>y>>z;
road[x+0*n].push_back(make_pair(y+0*n, 0));
road[x+0*n].push_back(make_pair(y+1*n,-a[x]));
road[x+1*n].push_back(make_pair(y+1*n, 0));
road[x+1*n].push_back(make_pair(y+2*n, a[x]));
road[x+2*n].push_back(make_pair(y+2*n, 0));
if(z==2)
{
road[y+0*n].push_back(make_pair(x+0*n, 0));
road[y+0*n].push_back(make_pair(x+1*n,-a[y]));
road[y+1*n].push_back(make_pair(x+1*n, 0));
road[y+1*n].push_back(make_pair(x+2*n, a[y]));
road[y+2*n].push_back(make_pair(x+2*n, 0));
}
}
memset(dist,-0x7f,sizeof(dist));
dist[1]=0;
vis[1]=true;
q.push(1);
while(q.size())
{
int now=q.front();
q.pop();
vis[now]=false;
for(int i=0; i<road[now].size(); i++)
{
int id=road[now][i].first;
int val=road[now][i].second;
if(dist[now]+val>dist[id])
{
dist[id]=dist[now]+val;
if(!vis[id])
{
q.push(id);
vis[id]=true;
}
}
}
}
cout<<max(dist[n],dist[3*n])<<endl;
return 0;
}
完美切题 ∼ \sim ∼