题意:
给定n个点m条边的有向图,
边xi->yi一定满足xi<yi,
每个点有点权a(i),表示这个城市的黄金价格为a(i)。
现在你一定要选择一个点S,买1单位黄金,然后到达另外一个城市卖出,
问最大收益是多少(也可能是亏损)。
数据范围:n,m<=2e5
解法:
因为边x->y一定保证x<y,那么图就一定是DAG.
令d[i]表示可以到达点i的所有点(除了i本身)中的最小黄金价格.
如果能计算出d[i],那么答案就是max(a[i]-d[i]).
d[i]的计算在DAG上dp即可,用拓扑排序转移.
code:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=2e5+5;
vector<int>g[maxm];
int in[maxm];
int d[maxm];//d[i]表示能到达i的点的最小黄金价格
int a[maxm];
int n,m;
signed main(){
ios::sync_with_stdio(0);
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=m;i++){
int a,b;cin>>a>>b;
g[a].push_back(b);
in[b]++;
}
for(int i=1;i<=n;i++)d[i]=1e9;
queue<int>q;
for(int i=1;i<=n;i++){
if(!in[i]){
in[i]=-1;
q.push(i);
}
}
while(q.size()){
int x=q.front();q.pop();
for(int v:g[x]){
if(in[v]>0){
in[v]--;
d[v]=min(d[v],d[x]);
d[v]=min(d[v],a[x]);
if(!in[v]){
q.push(v);
}
}
}
}
int ans=-1e18;
for(int i=1;i<=n;i++){
if(in[i]!=-1){
ans=max(ans,a[i]-d[i]);
}
}
cout<<ans<<endl;
return 0;
}