P1073

· · 个人记录

最短路

题目传送门

具体思路(参考了《算法竞赛进阶指南》):

开两个数组 f1[x],f2[x] 分别表示 从1到x的最小买入价格,从x到n的最大卖出价格。

然后建两张图(一正一反),跑两遍SPFA或heap-dijkstra求两个数组,这里的条件不再是边权而改为了点权,所以不说是求最短路。

疯狂挂初始化,一上来默认数组初值为初始价格,后来发现并不是所有点都可以到,所以在维护的过程中,每取出一个点就与其初始价格比较即可,这样既避免了默认全部点可以到,也避免了计算不了该点初始价格。。算了不说了语文太差

代码(好长啊)

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define maxn 100001
#define maxm 500001
#define re register
using namespace std;
int read()
{
    int fu=1,num=0; char c; c=getchar();
    while((c>'9'||c<'0')&&c!='-') c=getchar();
    if(c=='-') fu=-1,c=getchar();
    while(c>='0'&&c<='9') num=num*10+c-'0',c=getchar();
    return fu*num;
}
struct edge{
    int to,next;
};
edge e1[maxm*2],e2[maxm*2];
queue <int> q;
int f1[maxn],f2[maxn],n,m,ans,p[maxn],tot1,last1[maxn],tot2,last2[maxn];
bool vis[maxn],b[maxn];
void add_edge(int x,int y)
{
    tot1++; e1[tot1].to=y; e1[tot1].next=last1[x]; last1[x]=tot1;
    tot2++; e2[tot2].to=x; e2[tot2].next=last2[y]; last2[y]=tot2;
}
void init()
{
    n=read(); m=read();
    for(re int i=1;i<=n;i++) p[i]=read();
    for(re int i=1;i<=m;i++)
    {
        int u,v,z;
        u=read(); v=read(); z=read();
        if(z==1) add_edge(u,v);
        else
        {
            add_edge(u,v); add_edge(v,u);
        }           
    }
}
void spfa_work()
{
    memset(f1,0x3f,sizeof(f1));
    q.push(1);
    while(!q.empty())
    {
        int x=q.front(); q.pop(); vis[x]=0;
        f1[x]=min(f1[x],p[x]);
        for(re int i=last1[x];i;i=e1[i].next)
            if(f1[x]<f1[e1[i].to])
            {
                f1[e1[i].to]=f1[x];
                if(!vis[e1[i].to])
                {
                    q.push(e1[i].to);
                    vis[e1[i].to]=1;
                }
            }
    }

    q.push(n);
    while(!q.empty())
    {
        int x=q.front(); q.pop(); vis[x]=0;
        f2[x]=max(f2[x],p[x]);
        for(re int i=last2[x];i;i=e2[i].next)
            if(f2[x]>f2[e2[i].to])
            {
                f2[e2[i].to]=f2[x];
                if(!vis[e2[i].to])
                {
                    q.push(e2[i].to);
                    vis[e2[i].to]=1;
                }
            }
    }

}
int main()
{
    init();
    spfa_work();
    ans=0;
    for(re int i=1;i<=n;i++) if(f2[i]!=f2[0])ans=max(ans,f2[i]-f1[i]);
    cout<<ans<<endl;
    return 0;
}