spfa-洛谷P1073 最优贸易

https://daniu.luogu.org/problem/show?pid=1073#sub
显然这道题目你只要找到任何路径上的最大值,最小值就好了;
那么对于点k
我们要知道1~k里面的最小值卖入;
还要知道k~里面的最大值卖出;
那么我们可以用spfa去求;
第一遍跑出min数组后去反向图跑max数组;
这样就好了;
这道题目用缩点进行dp也可以;

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#define Ll long long
using namespace std;
struct cs{
    int nxt,to;
}a[1000005];
int head[100005],ll;
int v[100005],ma[100005],mi[100005];
int q[2000005],l,r;
int IN[500005][3];
bool in[100005];
int n,m,x,y,z,ans;
void init(int x,int y){
    a[++ll].nxt=head[x];
    a[ll].to=y;
    head[x]=ll;
}
void spfa(int S,int E){
    l=0;r=1;
    q[1]=S;mi[S]=v[S];in[S]=1; 
    while(r>l){
        int x=q[++l];
        for(int k=head[x];k;k=a[k].nxt){
            if(mi[a[k].to]>min(mi[x],v[a[k].to])){
                mi[a[k].to]=min(mi[x],v[a[k].to]); 
                if(!in[a[k].to]){
                    q[++r]=a[k].to;
                    in[a[k].to]=1;
                }
            }
        }
        in[x]=0;
    }
}
void SPFA(int S){
    l=0;r=1;
    q[1]=S;ma[S]=v[S];in[S]=1; 
    while(r>l){
        int x=q[++l];
        for(int k=head[x];k;k=a[k].nxt){
            if(ma[a[k].to]<max(ma[x],v[a[k].to])){
                ma[a[k].to]=max(ma[x],v[a[k].to]); 
                if(!in[a[k].to]){
                    q[++r]=a[k].to;
                    in[a[k].to]=1;
                }
            }
        }
        in[x]=0;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&v[i]),mi[i]=1e9;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        IN[i][0]=x;
        IN[i][1]=y;
        IN[i][2]=z;
        init(x,y);
        if(--z)init(y,x);
    }
    spfa(1,n);
    memset(head,0,sizeof head); ll=0;
    for(int i=1;i<=m;i++){
        y=IN[i][0];
        x=IN[i][1];
        z=IN[i][2];
        init(x,y);
        if(--z)init(y,x);
    }
    SPFA(n);
    for(int i=1;i<=n;i++)ans=max(ans,ma[i]-mi[i]);
    printf("%d",ans);
}
posted @ 2017-04-01 11:29  largecube233  阅读(155)  评论(0编辑  收藏  举报