code1173 最优贸易

先正向从1点出发SPFA,获得min[i],就是到达i点能最低购买到的价格,(起始点到i的路上经过的最小值)

然后反向(将图反向),从n点开始SPFA,获得max[i],就是从i点到终点能够卖出的最大的价格,(终止点到i的路上经过的最大值)

然后就是寻找差价最大的i,输出答案即可。

代码:

#include<iostream>
#include<cstring>
#include<queue>
#define MAXM 500005
#define MAXN 100005
#define INF 0x3f3f3f3f
using namespace std;

int n,m;
struct edge{
    int to,next;
}eg1[MAXM],eg2[MAXM];
int head1[MAXN],head2[MAXN];
int cnt1=0,cnt2=0;
int num[MAXN];
int Max[MAXN]; int Min[MAXN];
bool vis[MAXN];
int ans=0;
queue<int> q;

void add1(int a,int b){
    cnt1++;
    eg1[cnt1].to=b;
    eg1[cnt1].next=head1[a];
    head1[a]=cnt1;
}
void add2(int a,int b){
    cnt2++;
    eg2[cnt2].to=b;
    eg2[cnt2].next=head2[a];
    head2[a]=cnt2;
}

int main(){
    freopen("1.in","r",stdin);
    memset(head1,-1,sizeof(head1));
    memset(head2,-1,sizeof(head2));
    
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>num[i];
    int a,b,c;
    for(int i=1;i<=m;i++){
        cin>>a>>b>>c;
        if(c==2){
            add1(b,a); add2(a,b);
        }
        add1(a,b); add2(b,a);
    }
    
    //spfa1
    memset(Min,0x3f,sizeof(Min));
    memset(vis,false,sizeof(vis));
    q.push(1); vis[1]=true; Min[1]=num[1];
    while(!q.empty()){
        int k=q.front(); q.pop();
        vis[k]=false;
        for(int i=head1[k];i!=-1;i=eg1[i].next){
            int u=eg1[i].to;
            if(Min[u]>Min[k]){
                Min[u]=Min[k];
                if(!vis[u]){
                    q.push(u);
                    vis[u]=true;
                }
            }
            if(Min[u]>num[u]){
                Min[u]=num[u];
                if(!vis[u]){
                    q.push(u);
                    vis[u]=true;
                }
            }
        }
    }
    
    //spfa2
    memset(Max,0xf3,sizeof(Max));
    memset(vis,false,sizeof(vis));
    q.push(n); vis[n]=true; Max[n]=num[n];
    while(!q.empty()){
        int k=q.front(); q.pop();
        vis[k]=false;
        for(int i=head2[k];i!=-1;i=eg2[i].next){
            int u=eg2[i].to;
            if(Max[u]<Max[k]){
                Max[u]=Max[k];
                if(!vis[u]){
                    q.push(u);
                    vis[u]=true;
                }
            }
            if(Max[u]<num[u]){
                Max[u]=num[u];
                if(!vis[u]){
                    q.push(u);
                    vis[u]=true;
                }
            }
        }
    }
    
    ans=0;
    for(int i=1;i<=n;i++){
        //cout<<Min[i]<<' '<<Max[i]<<endl;
        if(ans<Max[i]-Min[i]){
            ans=Max[i]-Min[i];
        }
    }
    cout<<ans<<endl;
    
    return 0;
}

一开始疑问没有权值spfa怎么做...学习了!

原文地址:https://www.cnblogs.com/FuTaimeng/p/5611369.html