ABC188 E - Peddler(DAG上dp)

题意:

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

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/112712172